#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 ]
Related
I having hard time in solving those kind of question. In an exam I going to take in a few days, they show a program in C++ which has Multiple Inheritance:
struct X {
X(){cout << "X" << endl;}
};
struct A : virtual X {
int i;
A(){cout << "A" << endl;}
};
struct B : A {
int i;
B(){cout << "B" << endl;}
virtual void f() {cout << "f" << endl;}
};
struct C : A {
int i;
C(){cout << "C" << endl;}
C(int i){cout << "C2" << endl;}
virtual void g() {cout << "g" << endl;}
};
struct D : virtual B, virtual C {
int i;
D( int i) : C(i), B() {cout << "D" << endl;}
};
And show some code from main:
D* d = new D(2014);
C* c = d;
B* b = d;
And than ask "what will be the output?" I don't need the solution, I can always
just run or debug it but I need to understand the intuition because I will not have the debugger with me on the exam. Now I know the algorithm I need to follow:
5 Initialization shall proceed in the following order:
— First, and only for the constructor of the most derived class as
described below, virtual base classes shall be 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 class names in the derived class
base-specifier-list.
— Then, direct base classes shall be initialized in declaration order
as they appear in the base-specifier-list (regardless of the order of
the mem-initializers).
— Then, nonstatic data members shall be initialized in the order they
were declared in the class definition (again regardless of the order
of the mem-initializers).
— Finally, the body of the constructor is executed. [Note: the
declaration order is mandated to ensure that base and member
subobjects are destroyed in the reverse order of initialization. ]
But I really having bad time solving them, it does not make any sense. Is it possible to show the intuition, maybe a trick or tip on solving those kind of questions? Maybe to show dark corners? Maybe somehow to write down all the classes/structs, write the vbase classes somehow in order to easy see to output?
I read the following piece of code somewhere, as an example to solve the diamond problem in case of multiple inheritance :
#include<iostream>
using namespace std;
class A
{
int x;
public:
A() {}
A(int i) { x = i; }
void print() { cout << x; }
};
class B: virtual public A
{
public:
B():A(10) { }
};
class C: virtual public A
{
public:
C():A(100) { }
};
int main()
{
D d;
d.print();
return 0;
}
Suppose class D is defined as follows :
class D: public B, public C
{
public:
D():B(),C(){}
};
I get some garbage value in the print. And if the class D is defined as follows (parameterized constructor for A is explicitly called) :
class D: public B, public C
{
public:
D():B(),C(),A(20){}
};
I get 20 as output. In the first case, I can understand that the default A() constructor is called, hence the garbage value as x is not set to any value.
However, in the second case, its not clear. When is the parameterized constructor for A(int) is called? If I understood correctly, call order depends on order of inheritance. Since B is inherited first, B's constructor call takes precedence over C.Since B inherits A, A() will be called first, of all. Then B's constructor will be called. Then C's constructor will be called. At last, A(int) will be called, as A's constructor is called explicitly in class D. If this is the case, then the output is well justified for the second case. However, this, then contradicts the output for the below piece of code :
#include<iostream>
using namespace std;
class Person {
public:
Person(int x) { cout << "Person::Person(int ) called" << endl; }
Person() { cout << "Person::Person() called" << endl; }
};
class Faculty : virtual public Person {
public:
Faculty(int x):Person(x) {
cout<<"Faculty::Faculty(int ) called"<< endl;
}
};
class Student : virtual public Person {
public:
Student(int x):Person(x) {
cout<<"Student::Student(int ) called"<< endl;
}
};
class TA : public Faculty, public Student {
public:
TA(int x):Student(x), Faculty(x), Person(x) {
cout<<"TA::TA(int ) called"<< endl;
}
};
int main() {
TA ta1(30);
}
The output for this program :
Person::Person(int ) called
Faculty::Faculty(int ) called
Student::Student(int ) called
TA::TA(int ) called
Why Person(int) called at the beginning in this case, and not at the last?
N4594 12.6.2/13:
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 ]
Construction always starts from the base class. If there are multiple base classes then, it starts from the left most base. (side note: If there is a virtual inheritance then it's given higher preference). Then it comes the turn for member fields. They are initialized in the order they are declared. At the last the class itself is constructed.
The order of destructor is exactly reverse
Since B inherits A, A() will be called first, of all. Then B's
constructor will be called.
This is not quite true when A is virtually inherited.
When a class is virtually inherited, it is effectively inherited by the most derived class, for the purpose of invoking constructors and destructors. That's what virtual inheritance between.
Since D derives from B and C, in that class hierarchy D inherits A when it comes to invoking constructors and destructors, because D is the most-derived class.
With virtual inheritance, constructor of the virtual class is called only in the most derived class.
And order of initialization doesn't depend of order of initialization list, but to the order of declaration inside the class.
This question already has answers here:
Are parent class constructors called before initializing variables?
(7 answers)
Closed 7 years ago.
I have the following code:
class A{
public:
A(int* i){
std::cout << "in A()" << i << std::endl;
}
};
class B: public A{
public:
B(): i{new int{10}}, A{i}{
std::cout << "in B()" << std::endl;
}
private:
int* i;
};
int main()
{
B b;
}
In A constructor I have 0 (which is expected). But I want to initialize i before. Is it possible at all?
i is a data member of class B, so in order to be created, an object of class B has to be created first. So the answer, is no.
No, it is not possible since the base class initialization is always prior to derived class initialization.
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.
Initialize member before base constructor. Possible?
No, that is not possible. The standard mandates that the base classes be initialized first before the members of the class are initialized.
B(): i{new int{10}}, A{i}{
std::cout << "in B()" << std::endl;
}
is transformed to:
B(): A{i}, i{new int{10}}{
std::cout << "in B()" << std::endl;
}
I am studying for my final exam. I stumbled upon this question from previous years and I can't seem to fully understand whats happening.
Given this code, determine the output
#include <iostream>
using namespace std;
struct A {
A(int a): _a(a) {cout << "A::A, a=" << _a << endl;}
~A() { cout << "A::~" << endl; }
int _a;
};
struct B: public A
{
B(int b):A(b) { cout << "B::B" << endl; }
~B() { cout << "B::~" << endl; }
};
struct C: public B
{
A a;
B b;
C(int a=10, int b=20):a(a), b(a*b), B(b) {}
~C() { cout << "C::~" << endl; }
};
int main() {
C allTogetherNow;
return 0;
}
I tried to compile the code and I was given a warning:
warning: field 'b' will be initialized after base 'B'
[-Wreorder] C(int a=10, int b=20):a(a), b(a*b), B(b) {} ~C() { cout << "C::~" << endl; }
^ 1 warning generated.
and the following output:
A::A, a=20
B::B
A::A, a=10
A::A, a=200
B::B
C::~
B::~
A::~
A::~
B::~
A::~
The destruction order is kind of clear (last constructed - first destructed), but I can't seem to get ahold of the construction order/pattern.. What am I missing? A clarification of the Warning I received would be extra helpful. Also, if you could refer me to extra reading material on this particular subject.
Thank you.
The initialization order is precisely defined in the standard:
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.
So when you intialize C, its base class is first initialised, i.e. B with default 20 which itself requires A to be initialised first with 20. Only then is initialisation of B completed.
Then, A and B being intialized, the members of C are initalized, starting first with a with the default parameter 10, then with b(200). As b is a B, it will first require the initializeation of its own base A. Then initialisation of of b can be completed. And finally the initialisation of C is completed.
By the way, it's not part of the question but remember for your exam:
12.4/7: Bases and members are destroyed in the reverse order of the completion of their constructor.
Note about the warning:
My compiler doesn't generate this warning. There is no reason for it, as the mem-initilizer B(b) clearly uses the parameter b of your consturctor. It's only an hypotheses, but I suspect your compiler raise a false positive because b is also the name of a member (which would indeed not be initialised when calling the base). If I'm right, the following change should not raise a warning anymore:
C(int a=10, int bbb=20):a(a), b(a*bbb), B(bbb) { cout << "C::C" << endl;}
This line:
C(int a=10, int b=20):a(a), b(a*b), B(b) {}
Should be:
C(int a=10, int b=20): B(b), a(a), b(a*b) {}
In C++, the initialization order is fixed. For your type C, it will always be:
Base Class B
Member variable A a;
Member variable B b;
In your initializer list you ordered it differently. And so your compiler warned you in case you expected the initializer list's order to matter.
This question already has an answer here:
Why is Default constructor called in virtual inheritance?
(1 answer)
Closed 9 years ago.
In the following code when I create the object of C then A'a default constructor is getting called through B's constructor, why is that happening?
#include <iostream>
using namespace std;
class A
{
public:
int a;
A(int z): a(z) {cout<<"a is "<<a;}
A() { cout<<" it came here\n";}
};
class B: public virtual A
{
public:
B(int z): A(z) {cout<<"in B and z is "<<z<<"\n"; }
};
class C:public B
{
public:
C(int z): B(z) {cout<<" In C\n"; }
};
int main()
{
C b(6);
cout<<b.a;
return 0;
}
That's how virtual inheritance is described in the standard.
[12.6.2] — 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.
In particular, when constructing C, the A subobject is initialized before anything else (including the B subobject). Since A is not in the mem-initializers list of the offending C constructor, the default constructor of A is used for that.
[12.6.2] — 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 the B subobject is constructed.
[12.6.2] A mem-initializer where the mem-initializer-id denotes a virtual base class is ignored during execution of a constructor of any class that is not the most derived class.
: A(z) in the constructor of B is ignored when constructing the B subobject of C.
In the everyday language this means you have to initialize a virtual base class in each direct or indirect derived class, as if it were a direct derived class. If you forget to do so, a default constructor will be forced, with potentially devastating consequences. (That's why you should strive to have either only the default constructor or no default constructor at all in any virtual base class).