#include <iostream>
using namespace std;
struct A{
A() {cout << "A" << endl;}
A(int a) {cout << "A+" << endl;}
};
struct B : virtual A{
B() : A(1) {cout << "B" << endl;}
};
struct C : virtual A{
C() : A(1) {cout << "C" << endl;}
};
struct D : virtual A{
D() : A() {cout << "D" << endl;}
};
struct E : B, virtual C, D{
E(){cout << "E" << endl;}
};
struct F : D, virtual C{
F(){cout << "F" << endl;}
};
struct G : E, F{
G() {cout << "G" << endl;}
};
int main(){
G g;
return 0;
}
Program prints:
A
C
B
D
E
D
F
G
I would like to know what rules should I use to determine in what order constructors get called. Thanks.
You should follow the rules given in the C++ standard:
[C++11: 12.6.2/10]:
In a non-delegating constructor, initialization proceeds in the following order:
- First, and only for the constructor of the most derived class (1.8), virtual base classes are initialized in the order they appear on a depth-first left-to-right traversal of the directed acyclic graph of base classes, where “left-to-right” is the order of appearance of the base classes in the derived class base-specifier-list.
- Then, direct base classes are initialized in declaration order as they appear in the base-specifier-list (regardless of the order of the mem-initializers).
- Then, non-static data members are initialized in the order they were declared in the class definition (again regardless of the order of the mem-initializers).
- Finally, the compound-statement of the constructor body is executed.
[ Note: The declaration order is mandated to ensure that base and member subobjects are destroyed in the reverse order of initialization. —end note ]
Virtual base subobjects are constructed first, by the most-derived class, before any other bases. This is the only way that makes sense, since the relation of the virtual bases to tbe most-derived object is not known until object construction, at runtime (hence "virtual"). All intermediate initializers for virtual bases are ignored.
So, what are your virtual bases? G
derives from E
and F
. E
derives virtually from C
, which in turn derives virtually from A
, so A
, C
are first. Next, F
doesn't add any further virtual bases. Next, E
has non-virtual bases B
and D
, in that order, which are constructed next, and then E
is complete. Then comes F
's non-virtual base D
, and F
is complete. Finally, G
is complete.
All in all, it's virtual bases A
, C
, then non-virtual bases B
, D
, E
and D
, F
, and then G
itself.
You can investigate the order of constructor calls from this quote of the C++ Standard and try to trap it yourself
10 In a non-delegating constructor, initialization proceeds in the
following order: — First, and only for the constructor of the most
derived class (1.8), virtual base classes are initialized in the order
they appear on a depth-first left-to-right traversal of the directed
acyclic graph of base classes, where “left-to-right” is the order of
appearance of the base classes in the derived class
base-specifier-list. — Then, direct base classes are initialized in
declaration order as they appear in the base-specifier-list
(regardless of the order of the mem-initializers). — Then, non-static
data members are initialized in the order they were declared in the
class definition (again regardless of the order of the
mem-initializers). — Finally, the compound-statement of the
constructor body is executed. [ Note: The declaration order is
mandated to ensure that base and member subobjects are destroyed in
the reverse order of initialization. —end note ]