class A: public B, public C { };
In this case order of execution is:
B(); // base(first)
C(); // base(second)
A(); // derived
class A: public B, virtual public C { };
But in this case,when i write virtual with class c while inheriting,order of
// execution becomes:
C(); // virtual base
B(); // ordinary base
A(); // derived
i have read somewhere that order of calling constructor depends on the order of declaration while inheriting multiple classes but how does the order of execution gets changed on writing virtual with a class.I am not able to get why i am getting such result.
The virtual base class constructors are always executed first according to the C++ standard. From the working draft N3242, page 272 line 10, we learn that:
Virtual base class constructors go first, in the order of a left-to-right depth-first traversal of the inheritance graph.
Direct base classes go next, in declaration order.
So the behavior you see is exactly what is required in the C++ standard. It makes sense, because the virtual base classes may show up multiple times in the inheritance and of course they can each only be constructed once. Hence there has to be an initial round of virtual base class construction, followed by the usual non-virtual base class construction.
There is also a nice explanation on this page.
If you have a virtual class as a parent, you cannot hope that initialization goes always in the order of declaration. In fact it is possible that the first (say non-virtual) parent class has itself a dependency on the virtual class. Hence in that case the virtual class must be constructed first.
I think this is the reason why C++ specification says that initializers of virtual parent classes get always executed first. As shown by #Dan Roche there is a predictable order of initialization.
Example:
class B: public A {...}
class C: public B, virtual A {...}
In this example in C's initialization it is not possible to initialize B before A since B's initialization requires A to be initialized first.
another example
This example is to show that you shouldn't rely on base class initialization order:
#include <iostream>
using namespace std;
struct A {
A() {cout<<"A()"<<endl;}
};
struct B {
B() {cout<<"B()"<<endl;}
};
struct C: virtual A, virtual B {
C() {cout<<"C()"<<endl;}
};
struct D: virtual B, virtual A, C {
D() {cout<<"D()"<<endl;}
};
int main() {
cout<<"construct C"<<endl;
new C;
cout<<"construct D"<<endl;
new D;
}
output:
construct C
A()
B()
C()
construct D
B()
A()
C()
D()
As the example shows, when C is constructed as a base class of D, the order of initialization of A and B is reversed. This means that you cannot rely on the order of initialization of virtual base classes if you want that somebody could extend your class.
Related
The situation is (hopefully) clear with the code. We have two (in this example pure abstract, but that isn't necessary) classes. Is this possible to define the class C? What happens to the pointer c_ptr? Do I need to delete it in the class B destructor?
class C : public B {
private:
public:
C();
~C();
int do();
};
class B : public A {
private:
C *c_ptr;
public:
B(){
c_ptr = new C();
}
~B() {
delete c_ptr;
}
virtual int do() = 0;
};
class A {
private:
public:
A();
~A();
virtual int do() = 0;
};
In short, no, this is not possible.
In your example we have the following constraints:
B is child of A
C is child of B is child of A
For every super class, there must be an object created as well. So for the instantiation of a B, there will be created an A first.
The same way for a C there will be constructed a B which will create an A first.
As C++ is a procedural language, datatypes and functions must be known BEFORE using them. However, it is not possible for the compiler to know how to build a C before knowing how to build a B and vice versa. Therefore it is not possible to do so.
However, this polymorphism structure may be accomplished by using something called Forward Declaration. Basically you tell the compiler that there is some class C which will be specified later on. Example in CompilerExplorer
Consider the following code:
class A {
};
class B : public A {
};
class C : public B{
public:
C() : A() {} // ERROR, A is not a direct base of B
};
In this case GCC (4.8.1, C++99) gives me the correct error (I understand this behavior):
prog.cpp:12:8: error: type āaā is not a direct base of ācā
However if the inheritance between b and a is virtual, this does not happen:
class A {
};
class B : virtual public A {
};
class C : public B{
public:
C() : A() {} // OK with virtual inheritance
};
Why does this work?
Is A now considered a direct base to C by the compiler?
In general, because this is how C++ tries to resolve the diamond inheritance problem http://en.wikipedia.org/wiki/Multiple_inheritance#The_diamond_problem (whether or it is a good or bad solution is left as an exercise to the reader).
All inheritance is a combination of an is-a and a has-a relationship...you must instantiate an instance of the parent. If you have the following classes:
class a;
class b : a;
class c : a;
class d : b,c;
Then you've instantiated an a for each b and c. d will not know which a to use.
C++ solves this by allowing virtual inheritance, which is high-overhead inheritance that allows b and c to share the same a if inherited in d (it is much more complicated than that, but you can read up on that on your own).
The most derived type in the chain needs to be able to override the instantiation of the shared class to control disparities in the way that the shared class is inherited in the parent classes. Take the following example:
class a {int x; public: a(int xx) {x=xx;} int get_x() {return x;}};
class b : public virtual a { public: b(): a(10){}};
class c : public virtual a { public: c(): a(15){}};
class d : public virtual b, public virtual c {public: d() : a (20) {}};
int main() {
d dd;
std::cout << dd.get_x() << std::endl;//20, d's constructor "wins"
return 0;
}
If d did not define what a was instantiated as, it would have definitions for conflicting instantiations (from b and c). C++ handles this by forcing the most derived class in the inheritance chain to instantiate all parent classes (the above would barf if d did NOT explicitly instantiate a, though if a supplied a default constructor that could be implicitly used) and ignoring all parent instantiations.
Why does this work?
According to the standard (10.1.4 in the FIDS), "for each distinct baseclass that is specified virtual, the most derived object shall contain a single base class subobject of that type".
Virtual base is shared between all classes that derive from it for the instance of the object. Since a constructor may only be called once for a given instaniation of an object, you have to explicitly call the constructor in the most derived class because the compiler doesn't know how many classes share the virtual base. This is because the compiler will start from the most base class's constructor and work to the most derived class. Classes that inherit from a virtual base class directly, will not, by the standard, call their virtual base classes constructor, so it must be called explicitly.
From N3337, 12.6.2
Initializing bases and members
In the definition of a constructor for a class, initializers for direct and virtual base subobjects and non-static data members can be specified by a ctor-initializer, which has the form
Perhaps someone who has better version of Standard can verify this.
#include<iostream.h>
class A{
public:
int i;
A(int j=3):i(j){}
};
class B:virtual public A{
public:
B(int j=2):A(j){}
};
class C:virtual public A{
public:
C(int j=1):A(j){}
};
class D:public B, public C {
public:
D(int j=0):A(j), B(j+1), C(j+2){}
};
int main()
{
D d;
cout<<d.i;
return 0;
}
I am not being able to understand how the final output is zero. Every time j is initialized in default way to some fixed value, how is the value initialized in the constructor of class D being passed to class A?
Since A is a virtual base class, it should be constructed only once, so it is not possible to create it with different constructor parameters, and the C++ compiler has to choose one way of creating a base class.
The obvious question is: which one is used?
And the rule is: the one specified in the most derived class that inherits A directly.
The initialization order is simple: first A (with the parameter value from D constructor initialization list), then B (it is D's first ancestor; and it uses the instance of A created before), then C (and it shares the same A instance), finally D (and it also shares the same A object as B and C).
The rule with virtual base inheritance is:
"The most derived class in a hierarchy must construct a virtual base"
In your case, from the most derived class D You explicitly called the constructor of A by passing an argument 0 So it sets the i to 0. As mentioned in rule virtual base class is constructed through most derived class only and the other constructor calls through intermediate hierarchy have no effect since it is only constructed once.
The order of calling is:
A(int)
B(int)
C(int)
Good Read:
Why virtual base class constructors called first?
Suppose there is this interface:
class A{
public:
virtual foo()=0;
};
And a class B which implements this interface:
class B:public A{
public:
virtual foo(){} //Foo implemented by B
}
Finally, a class C which has classes A and B as base classes:
Class C : public A, public B {
};
My question is, there is a way to tell the compiler that the implementation for foo is the one from class B without doing an explicit call to B::foo()?
As #BenVoigt pointed out in the comments, the below answer only works due to a bug in g++ (meaning it isn't guaranteed to keep working, and it definitely isn't portable). Thus, although it may do what you want if you use a particular (buggy) compiler, it isn't an option you should use.
Do use virtual inheritance though.
This isn't exactly the scenario that the code in the question implies, but the sentence
My question is, there is a way to tell the compiler that the
implementation for foo is the one from class B without doing an
explicit call to B::foo()?
seems to be asking for syntax to distinguish between multiple base versions of a function without using the :: qualifier.
You can do this with the using directive:
#include <iostream>
class A {
public:
A(){}
virtual void foo(){std::cout<<"A func";}
};
class B: virtual public A {
public:
B(){}
virtual void foo(){std::cout<<"B func";}
};
class C:virtual public A, virtual public B {
public:
C(){}
using A::foo; // tells the compiler which version to use
// could also say using B::foo, though this is unnecessary
};
int main() {
C c;
c.foo(); // prints "A func"
return 0;
}
Of course, the code itself in the question doesn't require this at all, as the other answers have pointed out.
Just use virtual inheritance, so that the A subobject provided by B is the same object used in C.
Or write class C : public B... it will be implicitly usable as an A anyway, via the base class B.
Before the question was edited:
B::foo is not compatible with A::foo.
The required signature is
ReturnType /* missing from question */ foo(A* const this /* this parameter is implicit */);
But B::foo has the signature
ReturnType foo(B* const this);
An A*, which will be passed to the virtual function, is not a B*, which the implementation requires. If B inherited from A, then the compiler would generate B::foo to accept an A* const subobject and find the B* const this object from that subobject pointer. But B::foo has no knowledge of the relationship in C.
As you have the two base classes in your example (which might be a design issue/design smell, I'd review that) you have to explicitly call the implementation that you are after, be it A::foo() or B:foo().
If all B does is to provide the implementation of foo() I'd consider moving the implementation into A (you can provide an implementation for a pure virtual function) but even in this case you'd have to call it via its qualified name.
For many classes C1, C2, and so forth, the initialization looks equal, and it's just a little something differs from class to class. Hence I created a base class B that hosts the initalizations, e.g.:
class B {
public:
B()
{
// complex initializations
int a = doSomething();
// more complex stuff with `a`
};
virtual int doSomething()
{return 2 * doSomethingHelper();}
protected:
virtual int doSomethingHelper() = 0;
};
class C: public B {
protected:
virtual int doSomethingHelper()
{return 1;}
};
int main() {
C c;
return 0;
}
This code fails with
pure virtual method called
terminate called without an active exception
Aborted (core dumped)
since doSomethingHelper() is used to initialize B.
I'm wondering if there is a better design. My objectives are:
Make C's user interface as easy as possible: C has no constructor arguments.
Make C itself as minimalistic as possible such that other concretizations of B are short. Ideally, it only contains the doSomethingHelper.
A suggestion for a more sane design would be appreciated.
Short answer:
Don't call virtual functions from within a constructor. Doing so will get you in trouble.
Longer answer:
The declaration C c creates and constructs, in steps, an instance of class C. That object is first constructed as a class A object, then as a class B object, and finally as a class C object. At the point that B::B() is called, there is no notion that the object will eventually be an instance of class C.
When B::B() is invoked, it calls the virtual function doSomething(), which in this case means calling B::doSomething(). There's no problem yet; that function exists. The problem is with the call to doSomethingHelper() within the body of B::doSomething(). That function is pure virtual at this point. As noted above, there is no indication that this object will eventually be an instance of class C. The function C::doSomethingHelper() cannot be called cannot be called from B::B() or A::A(). There is no A::doSomethingHelper(), no B::doSomethingHelper(), so the function doesn't exist. You're toast.
I'm wondering if there is a better design.
There are lots of better designs. The simplest is to not call doSomething() from within the constructor of class B. Move that call to the constructor of class C. Even then, calling a virtual function from within the constructor may not be a good idea. What if class D inherits from class C and overrides C::doSomethingHelper()? An instance of class D will be constructed by calling C::doSomethingHelper() rather than D::doSomethingHelper().
According to the standard:
10.4/6: Member functions can be called from a constructor (or destructor) of an abstract class; the effect of making a virtual call
(10.3) to a pure virtual function directly or indirectly for the
object being created (or destroyed) from such a constructor (or
destructor) is undefined
This is because, when you construct C:
first the subobject B is constructed using the B() constructor. At that time, it's still B's virtual functions which are used. You get the error because at this moment, doSomethingHelper() is not defined for it.
Only once B() is completed will the virtual will C's virtual functions become active.
Two phased initialisation
This situation can only be avoided through a two phased initialisation: first construction, then calling an initialisation function. Not so nice and user friendly as you'd have desired.
class B {
public:
B() { /* complex initializations */ }
...
protected:
void init() { // the rest of the what you wanted in constructor
int a = doSomething();
// more complex stuff with `a`
}
};
The two phased initialisation could then be triggered via C's constructor:
class C {
public:
C() : B() { // first B is constructed
init(); // then the body of C's constructor is executed
}
...
};
Variant for the two-phased initialisation
There's a small variant that you can use, to hide the two phase approach, and let more freedom for the user about defining or not their own constructor.
In B you define an auxiliary nested class:
protected:
class initialiser {
public:
initialiser(B*b) {b->init();} // the constructor launches the second phase init
};
In C , you just need to add a protected member variable:
class C: public B {
...
protected:
B::initialiser bi{this}; // this triggers automaticcaly the second phase
...
};
The standard's rules ensure that first B is constructed and then the members of C. Demo here.
You can't use dynamic dispatching to a derived class in a constructor.
When B's constructor is running, the C subobject has not yet been created, so none of its overriden functions can be used. As B doesn't provide an implementation for doSomethingHelper, nothing sensible can be done.
Move all the complexity into B::doSomething, and call that method from the end of inheritance chain, C:
class B {
public:
B()
{};
virtual int doSomething()
{
// complex initializations
int a = 2 * doSomethingHelper();
// more complex stuff with `a`
return a;
}
protected:
virtual int doSomethingHelper() = 0;
};
class C: public B {
public:
C(): B()
{
int a = doSomething();
}
protected:
virtual int doSomethingHelper()
{return 1;}
};
int main() {
C c;
return 0;
}
This might require you to make some of B formerly private members protected such that they can be initialized by C.