Yes i know the phrase "virtual constructor" makes no sense but i still see articles like this
one: http://www.informit.com/guides/content.aspx?g=cplusplus&seqNum=184
and i'v heard it mentioned as a c++ interview.
What is the general consensus?
Is a "Virtual Constructor" good practice or something to be avoided completely?
To be more more precise, can some one provide me with a real world scenario where they have had to use it, from where i stand this concept of virt. constr. is a somewhat useless invention but i could be wrong.
All the author has done is implement prototyping and cloning. Both of which are powerful tools in the arsenal of patterns.
You can actually do something a lot closer to "virtual constructors" through the use of the handle/body idiom:
struct object
{
void f();
// other NVI functions...
object(...?);
object(object const&)
object& operator = (object const&);
~object();
private:
struct impl;
impl * pimpl;
};
struct object::impl
{
virtual void f() = 0;
virtual impl* clone() = 0;
// etc...
};
struct impA : object::impl { ... };
struct impB : object::impl { ... };
object::object(...?) : pimpl(select_impl(...?)) {}
object::object(object const& other) : pimpl(other.pimpl->clone()) {}
// etc...
Don't know if anyone has declared this an Idiom but I've found it useful and I'm sure others have come across the same idea themselves.
Edit:
You use factory methods or classes when you need to request an implementation for an interface and do not want do couple your call sites to the inheritance tree behind your abstraction.
You use prototyping (clone()) to provide generic copying of an abstraction so that you do not have to determine type in order to make that copy.
You would use something like I just showed for a few different reasons:
1) You wish to totally encapsulate the inheritance relation behind an abstraction. This is one method of doing so.
2) You want to treat it as a value type at the abstract level (you'd be forced to use pointers or something otherwise)
3) You initially had one implementation and want to add new specifications without having to change client code, which is all using the original name either in an auto declaration or heap allocation by name.
The best way to write "virtual constructors" is to use a Prototype pattern with a Clone() virtual method wich calls the copy constructor of the real type of the object and returns a pointer to a base class.
class Base
{
public:
virtual Base* Clone() { return new Base(*this); }
};
class Derived : public Base
{
virtual Base* Clone() { return new Derived(*this); }
};
It's not considered a good practice and is to use only if you need it (implement a copy-paste function for example)
I consider these so-called "virtual constructors" a bad design when used instead of constructors. These are nothing but virtual functions that are supposed to be called at the beginning of use of an instance of a class.
From the link you've posted:
class Browser
{
public:
//virtual default constructor
virtual Browser* construct() {return new Browser;}
};
Let's add a member field:
class Browser
{
int member;
public:
//virtual default constructor
virtual Browser* construct() {return new Browser;}
};
We need to initialize the member field, how do we do it?
class Browser
{
int member;
public:
//virtual default constructor
virtual Browser* construct()
{
Browser* b = new Browser;
b->member = 0;
return b;
}
};
Consider a situation when someone forgets to use template <class T> void func(T & obj) and does something like this:
Browser b;
printf("member=%d", b.member);
This way an uninitialized field is used. There is no way to prevent it.
Now, in this case
class Browser
{
int member;
public:
Browser() : member(0) { }
virtual Browser* construct() { /* some init stuff */ return new Browser;}
};
the default constructor is always used and member field always initialized.
However calling the construct() a "virtual constructor" I consider a naming abuse.
The pattern I showed above is quite common eg. in MFC. CWnd and similar classes use constructors to init instances and Create(...) functions to fully init and create controls. I would never call the Create(...) function a "virtual constructor", anyway.
It's something you can use, but only when you really, really need it. Even the guy in the link said that it's only something that you use if desperate.
All the answer above doesn't answer the question but are giving some workaround. The answer to the above question is http://www.stroustrup.com/bs_faq2.html#virtual-ctor straight from the language author itself. In short it says you need complete information to construct an object, hence virtual constructor doesn't exist in C++.
Related
I have an idea to architecting classical entity-component in a better way with variadic template inheritance. This question stems from funky experiments in the context of 3d-graphics but i believe i have it broken down to a very abstract question about C++. I am able to use C++20 in the scope in which it is currently implemented in Microsoft cl aka. the MSVC++19-Toolchain.
So. A few Base classes:
class basic {
public:
std::wstring get_name() { return name; }
virtual void do_something_idk_virtual() = 0;
virtual ~basic() {}
private:
std::wstring name;
}
class has_legs {
public:
virtual void walk() = 0;
virtual ~has_legs() {}
}
class has_wings {
public:
virtual void fly() = 0;
virtual ~has_wings() {}
}
template<typename... Ts>
class entity : public basic, public Ts... {
public:
virtual ~entity() {}
}
So far, so good. Now i want to make a duck:
class duck : entity<has_wings, has_legs> {
public:
virtual ~duck() {}
virtual void walk() { cout << "walk" << endl; }
virtual void fly() { cout << "fly" << endl; }
virtual void do_something_idk_virtual() { } // nothing,
}
still, seems to work. The problem is: I know have data structure (say a linked_list, or some sort of graph) and I use the visitor-pattern to work with basic*-typed things. I now have a lot of Code that looks like this. This is, quite literally, the central and critical part of a my program:
void visit(basic* node) {
//here i find out, through magic or some other kind of out-of-scope-mechanism that node is at least a has_wings. Problem:
reinterpret_cast<has_wings*>(node)->fly(); //does not work, will call basic::do_something_idk_virtual(). As far as i understand, this is because the compiler-generated vtable does not change via the reinterpret_cast.
reinterpret_cast<entity<has_wings>*>(node)->fly(); //might, work, problems start to come in if node is of some type that has_wings and has_legs. It sometimes calls some other method, depending on the ordering in declaring the class.
}
Solution
Have every component (aka. the pure interfaces) and the entity-class virtually inherit from basic
in basic add the non-virtual method:
template<typename TComponent> TComponent* get_component() {
return dynamic_cast<TComponent*>(this);
}
This will then fix vtables. I am not sure why dynamic_cast does that.
First of all, your template gives you nothing. class duck : public basic, public has_wings, public has_legs is absolutely identical.
Second, you need to decide what your level of polymorphic access is. If your level is basic, than it has to have already defined all the virtuals you want to be accessing (i.e. has_wings, fly) An interface where you need dynamic_casts to arrive to correct dynamic type (your example with reinterpret_cast is just wrong, you can't use reinterpret_cast to move through class hierarchy) is a poorly written interface.
Sometimes visitor pattern can be employed, but in my mind, it tends to produce extremely hard to troubleshoot code.
You have to use static_cast or dynamic_cast to move within an inheritance hierarchy, and static_cast can’t descend virtual inheritance or cross-cast (in one step) because the layout of different classes that derive from the source and destination types may differ. As it is, you’d have to know the actual type (not just that it had a given aspect) to do the conversion. If you have your “aspect” classes inherit from basic—virtually, so that there is a unique basic* to be had—you can then use dynamic_cast not for its checking purpose but so as to find the appropriate vtable for the aspect in question.
If you can’t afford that, you may want to amalgamate the interfaces somehow. You then have to be careful to call the functions only when they’re meaningful; that’s already the case (“through magic”), but then the ordinary call syntax might be an attractive nuisance. You might also try some C-style polymorphism with a manually-created vtable with function pointers for each optional behavior.
Have seen some related questions, but not this exact one...
I've treated classes as fitting into a few major categories, let's say these four for simplicity:
Value Classes which have some data and a bunch of operations. They can be copied and meaningfully compared for equality (with copies expected to be equal via ==). These pretty much always lack virtual methods.
Unique Classes whose instances have identity that you disable assignment and copying on. There's usually not an operator== on these because you compare them as pointers, not as objects. These quite often have a lot of virtual methods, as there isn't risk of object-slicing since you're being forced to pass them by pointer or reference.
Unique-but-Clonable Classes which disable copying, but are pre-designed to support cloning if that's what you really want. These have virtual methods, most importantly those following the virtual construction / cloning idiom
Container Classes which inherit the properties of whatever they're holding. These tend not to have virtual methods...see for instance "Why don't STL containers have virtual destructors?".
Regardless of holding this informal belief system, a couple times I've tried adding a virtual method to something copyable. While I may have thought it would "be really cool if that worked", inevitably it breaks.
This led me to wonder if anyone has an actual good example of a type which has virtual methods and doesn't disable copying?
The only counter-example that I have are classes that are meant to be stack-allocated and not heap-allocated. One scheme I use it for is Dependency Injection:
class LoggerInterface { public: virtual void log() = 0; };
class FileLogger final: public LoggerInterface { ... };
int main() {
FileLogger logger("log.txt");
callMethod(logger, ...);
}
The key point here is the final keyword though, it means that copying a FileLogger cannot lead to object-slicing.
However, it might just be that being final turned FileLogger into a Value class.
Note: I know, copying a logger seems weird...
There's nothing inherently wrong in being able to copy a polymorphic class. The problem is being able to copy a non-leaf class. Object slicing will get you.
A good rule of thumb to follow is never derive from a concrete class. This way, non-leaf classes are automatically non-instantiable and thus non-copyable. It won't hurt to disable assignment in them though, just to be on the safe side.
Of course nothing is wrong with copying an object via a virtual function. This kind of copying is safe.
Polymorphic classes are normally not "value-classes" but it does happen. std::stringstream comes to mind. It'not copyable, but it is movable (in C++11) and moving is no different from copying with regard to slicing.
Virtual dispatch happens a runtime. The only reason one should want it is when the actual, dynamic type of an object cannot be known until runtime. If you already knew the desired dynamic type when writing the program, you could use different, non-virtual techniques (such as templates, or non-polymorphic inheritance) to structure your code.
A good example for the need for runtime typing is parsing I/O messages, or handling events – any kind of situation where one way or another you'll either have some sort of big switch table to pick the correct concrete type, or you write your own registration-and-dispatch system, which basically reinvents polymorphism, or you just use virtual dispatch.
(Let me interject a warning: Many people misuse virtual functions to solve problems that don't need them, because they're not dynamic. Beware, and be critical of what you see.)
With this said, it's now clear that your code will be dealing mostly with the polymorphic base classes, e.g. in function interfaces or in containers. So let's rephrase the question: Should such a base class be copyable? Well, since you never have actual, most-derived base objects (i.e. the base class is essentially abstract), this isn't really an issue, and there's no need for this. You've already mentioned the "clone" idiom, which is the appropriate analogue of copying in a polymorphic.
Now, the "clone" function is necessarily implemented in every leaf class, and it necessarily requires copying of the leaf classes. So yes, every leaf class in a clonable hierarchy is a class with virtual functions and a copy constructor. And since the copy constructor of a derived class needs to copy its base subobjects, all the bases need to be copyable, too.
So, now I believe we've distilled the problem down to two possible cases: Either everything in your class hierarchy is completely uncopyable, or your hierarchy supports cloning, and thus by necessity every class in it is copyable.
So should a class with virtual functions have a copy constructor? Absolutely. (This answers your original question: when you integrate your class into a clonable, polymorphic hierarchy, you add virtual functions to it.)
Should you try to make a copy from a base reference? Probably not.
Not with a single, but with two classes:
#include <iostream>
#include <vector>
#include <stdexcept>
class Polymorph
{
protected:
class Implementation {
public:
virtual ~Implementation() {};
// Postcondition: The result is allocated with new.
// This base class throws std::logic error.
virtual Implementation* duplicate() {
throw std::logic_error("Duplication not supported.");
}
public:
virtual const char* name() = 0;
};
// Precondition: self is allocated with new.
Polymorph(Implementation* self)
: m_self(self)
{}
public:
Polymorph(const Polymorph& other)
: m_self(other.m_self->duplicate())
{}
~Polymorph() {
delete m_self;
}
Polymorph& operator = (Polymorph other) {
swap(other);
return *this;
}
void swap(Polymorph& other) {
std::swap(m_self, other.m_self);
}
const char* name() { return m_self->name(); }
private:
Implementation* m_self;
};
class A : public Polymorph
{
protected:
class Implementation : public Polymorph::Implementation
{
protected:
Implementation* duplicate() {
return new Implementation(*this);
}
public:
const char* name() { return "A"; }
};
public:
A()
: Polymorph(new Implementation())
{}
};
class B : public Polymorph {
protected:
class Implementation : public Polymorph::Implementation {
protected:
Implementation* duplicate() {
return new Implementation(*this);
}
public:
const char* name() { return "B"; }
};
public:
B()
: Polymorph(new Implementation())
{}
};
int main() {
std::vector<Polymorph> data;
data.push_back(A());
data.push_back(B());
for(auto x: data)
std::cout << x.name() << std::endl;
return 0;
}
Note: In this example the objects are copied, always (you may implement shared semantics, though)
Consider the following code:
class Base
{
public:
virtual void Foo() {}
};
class Derived : public Base
{
private:
void Foo() {}
};
void func()
{
Base* a = new Derived;
a->Foo(); //fine, calls Derived::Foo()
Derived* b = new Derived;
// b->Foo(); //error
static_cast<Base*>(b)->Foo(); //fine, calls Derived::Foo()
}
I've heard two different schools of thought on the matter:
Leave accessibility the same as the base class, since users could use static_cast<Derived*> to gain access anyway.
Make functions as private as possible. If users require a->Foo() but not b->Foo(), then Derived::Foo should be private. It can always be made public if and when that's required.
Is there a reason to prefer one or the other?
Restricting access to a member in a subtype breaks the Liskov substitution principle (the L in SOLID). I would advice against it in general.
Update: It may "work," as in the code compiles and runs and produces the expected output, but if you are hiding a member your intention is probably making the subtype less general than the original. This is what breaks the principle. If instead your intention is to clean up the subtype interface by leaving only what's interesting to the user of the API, go ahead and do it.
Not an answer to your original question, but if we are talking about classes design...
As Alexandrescu and Sutter recommend in their 39th rule, you should prefer using public non-virtual functions and private/protected virtual:
class Base {
public:
void Foo(); // fixed API function
private:
virtual void FooImpl(); // implementation details
};
class Derived {
private:
virtual void FooImpl(); // special implementation
};
This depends on your design, whether you want to access the virtual function with a derived class object or not.
If not then yes, it's always better to make them private or protected.
There is no code execution difference based on access specifier, but the code becomes cleaner.
Once you have restricted the access of the class's virtual function; the reader of that class can be sure that this is not going to be called with any object or pointer of derived class.
I know that it's OK for a pure virtual function to have an implementation. However, why it is like this? Is there conflict for the two concepts? What's the usage? Can any one offer any example?
In Effective C++, Scott Meyers gives the example that it is useful when you are reusing code through inheritance. He starts with this:
struct Airplane {
virtual void fly() {
// fly the plane
}
...
};
struct ModelA : Airplane { ... };
struct ModelB : Airplane { ... };
Now, ModelA and ModelB are flown the same way, and that's believed to be a common way to fly a plane, so the code is in the base class. However, not all planes are flown that way, and we intend planes to be polymorphic, so it's virtual.
Now we add ModelC, which must be flown differently, but we make a mistake:
struct ModelC : Airplane { ... (no fly function) };
Oops. ModelC is going to crash. Meyers would prefer the compiler to warn us of our mistake.
So, he makes fly pure virtual in Airplane with an implementation, and then in ModelA and ModelB, put:
void fly() { Airplane::fly(); }
Now unless we explictly state in our derived class that we want the default flying behaviour, we don't get it. So instead of just the documentation telling us all the things we need to check about our new model of plane, the compiler tells us too.
This does the job, but I think it's a bit weak. Ideally we instead have a BoringlyFlyable mixin containing the default implementation of fly, and reuse code that way, rather than putting code in a base class that assumes certain things about airplanes which are not requirements of airplanes. But that requires CRTP if the fly function actually does anything significant:
#include <iostream>
struct Wings {
void flap() { std::cout << "flapping\n"; }
};
struct Airplane {
Wings wings;
virtual void fly() = 0;
};
template <typename T>
struct BoringlyFlyable {
void fly() {
// planes fly by flapping their wings, right? Same as birds?
// (This code may need tweaking after consulting the domain expert)
static_cast<T*>(this)->wings.flap();
}
};
struct PlaneA : Airplane, BoringlyFlyable<PlaneA> {
void fly() { BoringlyFlyable<PlaneA>::fly(); }
};
int main() {
PlaneA p;
p.fly();
}
When PlaneA declares inheritance from BoringlyFlyable, it is asserting via interface that it is valid to fly it in the default way. Note that BoringlyFlyable could define pure virtual functions of its own: perhaps getWings would be a good abstraction. But since it's a template it doesn't have to.
I've a feeling that this pattern can replace all cases where you would have provided a pure virtual function with an implementation - the implementation can instead go in a mixin, which classes can inherit if they want it. But I can't immediately prove that (for instance if Airplane::fly uses private members then it requires considerable redesign to do it this way), and arguably CRTP is a bit high-powered for the beginner anyway. Also it's slightly more code that doesn't actually add functionality or type safety, it just makes explicit what is already implicit in Meyer's design, that some things can fly just by flapping their wings whereas others need to do other stuff instead. So my version is by no means a total shoo-in.
Was addressed in GotW #31. Summary:
There are three main reasons you might
do this. #1 is commonplace, #2 is
pretty rare, and #3 is a workaround
used occasionally by advanced
programmers working with weaker
compilers.
Most programmers should only ever use #1.
... Which is for pure virtual destructors.
There is no conflict with the two concepts, although they are rarely used together (as OO purists can't reconcile it, but that's beyond the scope of this question/answer).
The idea is that the pure virtual function is given an implementation while at the same time forcing subclasses to override that implementation. The subclasses may invoke the base class function to provide some default behavior. The base cannot be instantiated (it is "abstract") because the virtual function(s) is pure even though it may have an implementation.
Wikipedia sums this up pretty well:
Although pure virtual methods
typically have no implementation in
the class that declares them, pure
virtual methods in C++ are permitted
to contain an implementation in their
declaring class, providing fallback or
default behaviour that a derived class
can delegate to if appropriate.
Typically you don't need to provide base class implementations for pure virtuals. But there is one exception: pure virtual destructors. In fact if your base class has a pure virtual destructor, it must have an implementation. Why would you need a pure virtual destructor instead of just a virtual one? Typically, in order to make a base class abstract without requiring the implementation of any other method. For example, in a class where you might reasonably use the default implementation for any method, but you still don't want people to instantiate the base class, you can mark only the destructor as pure virtual.
EDIT:
Here's some code that illustrates a few ways to call the base implementation:
#include <iostream>
using namespace std;
class Base
{
public:
virtual void DoIt() = 0;
};
class Der : public Base
{
public:
void DoIt();
};
void Base::DoIt()
{
cout << "Base" << endl;
}
void Der::DoIt()
{
cout << "Der" << endl;
Base::DoIt();
}
int main()
{
Der d;
Base* b = &d;
d.DoIt();
b->DoIt(); // note that Der::DoIt is still called
b->Base::DoIt();
return 0;
}
That way you can provide a working implementation but still require the child class implementer to explicitely call that implementation.
Well, we have some great answers already.. I'm to slow at writing..
My thought would be for instance an init function that has try{} catch{}, meaning it shouldn't be placed in a constructor:
class A {
public:
virtual bool init() = 0 {
... // initiate stuff that couldn't be made in constructor
}
};
class B : public A{
public:
bool init(){
...
A::init();
}
};
Consider two classes
class A{
public:
A(){
}
~A(){
}
};
class AImpl : public A{
public:
AImpl(){
a = new AInternal();
}
AImpl(AInternal *a){
this->_a = a;
}
~AImpl(){
if(a){
delete a;
a = null;
}
}
private:
AInternal *a;
};
I am trying to hide the AInternal's implementation and expose only A's interface. Two things I see here
class A is totally empty.
Hiding is achieved basically through inheritance. I have to actually use downcasting and upcasting from A to AImpl and vice versa.
Is this a good design. Being very inexperienced in designing, I cannot see the pitfalls of it and why it is bad?
You're overcomplicating things by using 3 classes. I think what you're looking for is the pimpl idiom.
I am trying to hide the AInternal's implementation and expose only A's interface.
I think you are trying to do something like factory.
Here is an example:
class IA {
public:
IA() {}
virtual ~IA() {}
virtual void dosth() =0;
};
class Factory {
private:
class A : public IA {
public:
A () {}
virtual ~A() {}
void dosth() { cout << "Hello World"; }
};
public:
Factory () {}
virtual ~Factory() {}
IA*newA() { return new A; }
};
And the usage of Factory class:
Factory f;
IA*a = f.newA();
a->dosth();
return 0;
IMO AInternal makes no sense. Whatever you do there, should be done in AImpl. Otherwise, it's ok to do that in C++.
The code is rather obtuse, so I would be concerned with maintaining it six months down the road.
If you're going to do it this way, then the destructor ~A needs to be virtual.
You seem to be combining two common design features:
1) AInternal is a "pimpl". It provides for better encapsulation, for example if you need to add a new field to AInternal, then the size of AImpl doesn't change. That's fine.
2) A is an base class used to indicate an interface. Since you talk about upcasting and downcasting, I assume you want dynamic polymorphism, meaning that you'll have functions which pass around pointers or references to A, and at runtime the referands will actually be of type AImpl. That's also fine, except that A's destructor should either be virtual and public, or non-virtual and protected.
I see no other design problems with this code. Of course you'll need to actually define the interface A, by adding some pure virtual member functions to it that you implemented in AImpl. Assuming you plan to do that, there's nothing wrong with using an empty base class for the purpose which in Java is served by interfaces (if you know Java). Generally you'd have some kind of factory which creates AImpl objects, and returns them by pointer or reference to A (hence, upcasts them). If the client code is going to create AImpl objects directly then that might also be fine, and in fact you might not need dynamic polymorphism at all. You could instead get into templates.
What I don't see is why you would ever have to downcast (that is, cast an A* to AImpl*). That's usually bad news. So there may be some problems in your design which can only be revealed by showing us more of the definitions of the classes, and the client code which actually uses A and AImpl.