#include <iostream>
class A
{
public:
A() { std::cout << " A ctor" << std::endl; }
A(int i) { std::cout << " A ctor i" << std::endl; }
~A() { std::cout << " A dtor" << std::endl; }
};
class B: public A
{
public:
B() : A () { std::cout << " B ctor" << std::endl; }
~B() { std::cout << " B dtor" << std::endl; }
};
class C: public A
{
public:
B _b;
C() : _b (), A () { std::cout << " C ctor" << std::endl; }
~C() { std::cout << " C dtor" << std::endl; }
};
int main ()
{
C c;
}
The output is:
A ctor
A ctor
B ctor
C ctor
C dtor
B dtor
A dtor
A dtor
What is the order of the init. list? Why, in the init. list of C, ctor of A called before ctor of B? I thought the output should be:
A ctor
B ctor
A ctor
C ctor
C dtor
A dtor
B dtor
A dtor
Thanks.
The order in which you write initializations in the initialization list is not important, the order of initialization is determined independently of that list by other rules:
First the base class is initialized. That's why in the construction of C the base class constructor A is called first. Everything that belongs to the base class is constructed in this step (base classes and member variables belonging to the base class), just like when a normal object of that base class would be constructed.
Then the member variables of the derived class are initialized, in the order in which they are declared in the class. So if there are several member variables, the order in which they are declared determines the order in which they are initialized. The order of an initialization list is not important.
Base class constructors are called before derived class constructors. This allows the derived class to use members in the base class during their construction.
During destruction, the opposite is true. Subclass destruction occurs before the base class, for exactly the same reason.
If you think about it - it makes perfect sense. The base class has no knowledge of the subclass, but the opposite is not true. This determines the ordering in order for everything to work as expected.
I think your confusion is why is C's initialization list processed right to left instead of left to write. It is because, the compiler processes parameters in "last in first out" fashion. Hence the order: First A's c'tor. Since _b is an object of B which is derived from A, base class is constructed before the derived class so A c'tor is called and then B's c'tor. And finally, C's c'tor is called. When C's object is destructed, it follows the reverse order.
If you use GNU compiler, -Wall option will help you.
Related
I've started learning about virtual inheritance (and how it may solve problems of having a class derived from two parent classes with same parent). To better understand the mechanism behind it, i made a following example:
class A {
public:
A(string text = "Constructor A") { cout << text << endl; }
};
class B: public A {
public:
B(): A("A called from B") { cout << "Constructor B" << endl; }
};
class C : virtual public A {
public:
C() : A("A called from C") { cout << "Constructor C" << endl; }
};
class D : public B, public C {
public:
D() { cout << "Constructor D" << endl; }
};
I have class A, class B derived from A, class C virtually derived from A, and class D derived from B and C. In main i just form an object of class D: D d; and i get the following output
Constructor A
A called from B
Constructor B
Constructor C
Constructor D
What bothers me is, why is there "Constructor A" signalizing that it is not called by either class B or C. And why is there not "A called from C" before "Constructor C". For the latter one i know it has to do with the class C being virtually derived so i guess it does not call Constructor A again since object from class A has already been formed (twice in fact).
EDIT:
In main i just make one object type D.
int main() {
D d;
}
Firstly, since B derives from A non-virtually, D ends up with two A subobjects (as if you didn't use virtual inheritance at all).
The non-virtual A is constructed by B() (hence "A called from B"), and the virtual one prints "Constructor A" when constructed.
That's because the constructors of virtual (possibly indirect) bases are always called by the constructor of the most derived class (D), rather than by the constructors of any intermediate bases (C).
It means that : A("A called from C") in C() is ignored (since you're not constructing a standalone C). And since D() doesn't mention A in its member initializer list, the virtual A is constructed without any parameters (as if by : A()).
Also, it's worth mentioning that all virtual bases are constructed before the non-virtual ones.
So your code is guaranteed to print Constructor A before A called from B.
The problem
Your code forgot something and you still have two A objects in a D object. You can verify this claim by adding a public int test member to A and try the following code. You will get two different addresses:
D d;
cout << &d.B::test <<endl; // the non virtual A subobject of B
cout << &d.C::test <<endl; // the virtual A subobject of C
Online demo
The solution
All classes that share A virtually and that directly inherit from A must declare the virtual inheritance. So you need to correct class B:
class B: virtual public A {...} // you forgot the virtual here
The code snippets above would work as expected, and you could even address d.test without getting any ambiguity error. Online demo
Edit: The delicate construction of A
The C++ rules require each object with a virtual A sub-object to provide a constructor for A. In your case, D should provide for the virual A's construction.
Since there is no explicit constructor, D will look for a default-construct A. And it finds one, since you provide a default argument for the A constructor. It's misleading because it tells you "A constructor" when in reality it was D that used it.
If you remove this default argument, your code won't compile anymore. You then need something like this to get A properly constructed:
class A {
public:
int test;
A(string text) { cout << "A is constructed: "<<text << endl; }
};
class D : public B, public C {
public:
D() : A("Mandatory, if there is no default consructor") { cout << "Constructor D" << endl; }
};
Online demo
Why are the C++ construction rules like that ? Because when you have virtual inheritance, there is no reason that the A construction by B is drawn over the construction by C . Nor the contrary. On the other side, both B and C define how to construct their A sub-object. To solve the ambiguity in the choice of the right construction, this rule was decided. And it may be painful if the virtual class doesn't have a default constructor.
When a type has a virtual base, the virtual base gets constructed from the constructor of the most-derived type. So "Constructor A" is called from D's constructor.
A bit more detail:
#include <iostream>
struct base {
base() { std::cout << "base()\n"; }
base(int) { std::cout << "base(int)\n"; }
};
struct i1 : virtual base {
i1() : base(0) { std::cout << "i1()\n"; }
};
struct i2 : virtual base {
i2() : base(1) { std::cout << "i2()\n"; }
};
struct d : i1, i2 {
};
Now, if the code creates an object of type i1 the default constructor for i1 calls base(int), as written.
But when you create an object of type d, the constructor for d is responsible for constructing the base object. Since d does not have a default constructor, the compiler generates one that calls the default constructor for base before it calls the default constructors for i1 and i2.
int main() {
d d_obj;
return 0;
}
the output here is
[temp]$ Clang++ test.cpp
[temp]$ ./a.out
base()
i1()
i2()
[temp]$
Note that the constructors for i1 and i2 did not construct the base subobject. The compiler took care fo that: the base should only be initialized once, and the constructor for d did that.
If you want a different initialization for the base object, write that in the constructor:
d::d() : base(2) {}
adding that to the class d produces this output:
[temp]$ Clang++ test.cpp
[temp]$ ./a.out
base(int)
i1()
i2()
[temp]$
I understand that you can't expect to have a derived reference pointing at its base class because it will lose functionality, but I was curious on what would actually happen to understand more about the sequence of events.
#include <iostream>
struct Base
{
Base() { std::cout << "Base constructor" << std::endl; }
Base(const Base&) { std::cout << "Base copy constructor" << std::endl; }
~Base() { std::cout << "Base destructor" << std::endl; }
};
struct Derived : public Base
{
Derived(const Base& b) : Base(b) { std::cout << "Derived constructor" << std::endl; }
~Derived() { std::cout << "Derived destructor" << std::endl; }
};
struct OwnsDerived
{
OwnsDerived(const Derived& derivedObject) : derivedRef(derivedObject) { std::cout << "OwnsDerived created..." << std::endl; }
const Derived& derivedRef;
};
int main () {
std::cout << "Main starts: " << std::endl;
const Base b;
std::cout << "\nMain creating object that owns a reference to derived: " << std::endl;
OwnsDerived s(b);
std::cout << "\nMain ends: " << std::endl;
return 0;
}
The result I got was:
Main starts:
Base constructor
Main creating object that owns a reference to derived:
Base copy constructor
Derived constructor <-- why is a derived trying to be created when passing the wrong type in the constructor
OwnsDerived created...
Derived destructor //<-- these are treated as temporaries
Base destructor //<--
Main ends:
Base destructor
Even when I change the reference to be a copy of the object instead, it behaves similarly, which is also surprising to me.
I would really appreciate any pointers or any resources to learn about the more nuanced mechanics of these constructor/destructors!
OwnsDerived constructor takes a Derived by reference to const, but you pass a Base instance. So, the compiler will try to convert the Base instance to a Derived. That's possible by calling the (implicit) conversion constructor in Derived. So, a temporary instance of Derived is created.
To fix the implicit conversion, declare the Derived constructor as explicit.
struct Derived : public Base
{
explicit Derived(const Base& b);
//...
};
Reference to this https://www.tutorialspoint.com/cplusplus/cpp_functions.htm
In CPP when ever you call a function, it will copy the paramenter of that function instead of using it directly
So, when you call the contructor of OwnsDerived it use const Base b as it paramenter. The system will copy this to other memory where you get this log Base copy constructor. I will call this a copied_b. So copied_b is Base it will convert it to Derive as the contructor of OwnsDerived required a Derive so there is Derived constructor. I call this derived_of_copied_b. At the end of the contructor of OwnsDerived both copied_b and derived_of_copied_b will be destroy, where you will see Derived destructor and Base destructor right after OwnsDerived created....
I wish this could explain your question.
#include <iostream>
class A
{
public:
A() { std::cout << "A's constructor called\n"; }
};
class B
{
public:
B() { std::cout << "B's constructor called\n"; }
};
class C: public B, public A // Note the order
{
public:
C() { std::cout << "C's constructor called\n"; }
};
int main()
{
C c;
return 0;
}
Why is the constructor of class A and B called, when a new instance of C is created?
Output is
B's constructor called
A's constructor called
C's constructor called
C is derived from both A and B - so before the constructor for C can be executed, the constructors for A and B must both be completed. If that wasn't the case, then the C constructor could not rely on anything that its base classes provided.
For example, suppose A contained a list of items which is created and filed from a database in its constructor. All instances of A can rely on the list being complete because the constructor has to be finished before the instance is available to the rest of the code. But C is also an A - it derives from it in the same way that "a Ford" is also "A Car" - so it may well want to access that list. When you construct an instance, the base class constructors are automatically called before the derived classes to ensure that everything is ready for action when the derived constructor starts.
For example, change your code slightly:
class A
{
public:
A() { cout << "A's constructor called" << endl; }
};
class B: public A
{
public:
B() { cout << "B's constructor called" << endl; }
};
class C: public B
{
public:
C() { cout << "C's constructor called" << endl; }
};
int main()
{
C c;
return 0;
}
and you will get:
A's constructor called
B's constructor called
C's constructor called
Because the base class constructors are all completed before the derived ones are executed.
Why wouldn't it be? A C contains parts that are a B and an A respectively, and those parts need to be constructed as well. The constructor is the feature that performs this role.
kanishk tanwar's answer has more detail, but I was writing this anyway, so here's a very whistle stop tour of why it's happening to answer your question:
In order to ensure an instance of a class is properly initialised, a constructor for the base types are always called. If you don't specify which constructor you want to call (syntax: C() : B(), A() for C's constructor), the default constructor is used. As a derived class builds on a base class, the base classes have to be constructed first.
In your case you have specified contents to your default constructor, so that is the code that is run when you instantiate C.
I just want to understand the flow how it happens as am new to c++.
Let me elaborate my problem statement.
class test1 {
public:
test1() {
cout << " test1::constructor called" << endl;
}
~test1() {
cout << " test1::destrcutor called" << endl;
}
};
class test2 {
public:
test2() {
cout << " test2::constructor called" << endl;
}
~test2() {
cout << " test2::destrcutor called" << endl;
}
};
class derived :public test1, public test2 {
test2 t2;
test1 t1;
public:
derived() {
cout << " derived constructor called" << endl;
}
~derived() {
cout << "derived destructor called" << endl;
}
};
int main() {
derived d;
return 0;
}
The output of the above program shows
test1::constructor called
test2::constructor called
test2::constructor called
test1::constructor called
derived constructor called
derived destructor called
test1::destrcutor called
test2::destrcutor called
test2::destrcutor called
test1::destrcutor called
So here my question is at what points it called the constructor of the member variables in derived class as I have not put any initializer for the same.
The order of construction is bases, then members so :-
test1::constructor called << first base of 'derived'
test2::constructor called << second base of 'derived'
test2::constructor called << member of 'derived' t2
test1::constructor called << member of 'derived' t1
derived constructor called << code in 'derived::derived'
derived destructor called << code in 'derived::~derived'
test1::destrcutor called << destruction of t1
test2::destrcutor called << destruction of t2
test2::destrcutor called << destruction of derived
test1::destrcutor called << destruction of derived
There is only one destructor of an object, and it has a defined order to destroy objects. That is destroy all the members from bottom to top of the class.
Then destroy the class, and its bases in "reverse order".
Each constructor can choose what to initialize, but not the order.
a_class::a_class( params ) :
base_n( params ), base_n_1( params ),
member_1( params), member_2( params),...
This member initialization list allows different parameters to be given to construct all the bases and objects, but does not effect the order. It is always first_base, second_base, first_member, second_member, ...
This ordering is to ensure it is the opposite of the destructor.
These rules allowed me to work out which message was from the members, and which from the bases.
A member which does not get initialized from the member initialization list will still get its default constructor called test2::test2. As once a class/struct have a constructor, they will only come into existence by having a constructor called.
Plain-old-Data or POD are simple types such as int which don't have constructors. They are left uninitialized (whatever values were left behind in the memory).
I read that in virtual inheritance, constructors are called "from the most derived".
consider the following code. In my opinion, the most derived class here is D. then B and C and the "most-not-derived" is A.
So how come the most "Base" constructor is called first and not the "most derived"?
Thanks.
#include <iostream>
using namespace std;
struct A
{
A()
{
cout << "A default constructor" << endl;
}
};
struct B : virtual public A
{
B() : A()
{
cout << "B default constructor" << endl;
}
};
struct C : virtual public A
{
C() : A()
{
cout << "C default constructor" << endl;
}
};
struct D : public B, public C
{
D() : B(), C()
{
cout << "D default constructor" << endl;
}
};
int main()
{
D d;
}
This is the output :
A default constructor
B default constructor
C default constructor
D default constructor
UPDATE:
Ok. so consider the following code.
Notice that 10 was printed although D,B and C constructors sent 7.
Here actually the base class IS the first one that is called.
There was no chain from D to B to A.
A() was called first (actually it's default constructor). and only then B and C constructors were called.
But I read : "from the most derived."
Source : c++ virtual inheritance
the most derived here is D then B and C and only then A. So how come that A is called first without even considering the parameters B,D,C transfer to it from their constructors ?
Thanks.
The code :
#include <iostream>
using namespace std;
struct A
{
int _x;
A()
{
_x = 10;
cout << "A default constructor" << endl;
}
A(int x)
{
_x = x;
cout << "A NOT-default constructor" << endl;
}
};
struct B : virtual public A
{
B(int x=7) : A(x)
{
cout << "B constructor" << endl;
}
};
struct C : virtual public A
{
C(int x=7) : A(x)
{
cout << "C constructor" << endl;
}
};
struct D : public B, public C
{
D(int x=7) : B(x), C(x)
{
cout << "D constructor" << endl;
}
};
int main()
{
D d;
cout << d._x;
}
The output :
A default constructor
B constructor
C constructor
D constructor
10
Construction order is quite simple in C++:
You call a most-derived ctor (By initializing a variable; auto-storage-class, static, dynamic, whatever).
That ctor initializes all sub-objects:
A delegating ctor calls another most-derived-ctor.
A non-delegating ctor does the work itself:
Iff the most-derived ctor, virtual bases in left-first declaration-order. (That means arguments to the virtual-base ctor given by non-most-derived-ctors are ignored)
The other direct bases in left-first declaration-order.
The members in declaration-order.
The ctors body runs.
As your most-base ctor is for the only virtual base, its body is the first ctor-body to run, called directly by the most-derived ctor.
In general, calling virtual functions, typeid and dynamic_cast is safe, though not before the base-subobjects are all initialized: May I call a virtual function to initialize a base-class sub-object?
That means that it's the responsibility of the most derived class to initialise any virtual base sub-objects, as well as those that it immediately derives from. That is, all the base constructors are called from the most-derived constructor: the constructor for D calls the constructor for A, then B and C, and finally initialises itself. This is necessary to ensure that the shared base object is initialised just once, and before any of the classes that derive from it.
It doesn't mean that the order is from the most to least derived. As with regular inheritance, base sub-objects are always initialised first, so they're available when initialising the derived classes.
To answer your updated question, since D initialises A, it will call the default constructor unless its initialiser list contains an entry for A:
D(int x=7) : B(x), C(x) // calls A(), initialising with 10
D(int x=7) : A(x), B(x), C(x) // calls A(int), initialising with 7
Any entry for A in the initialiser list of B (or C) is only used when B (or C) is the most derived class (and so is responsibly for initialising A).
How do you propose any derived class to behave if its constructor code ran before the base class was constructed? While technically possible, it'd be entirely useless.
The behavior you observe is the only sane one, and has nothing to do with virtual inheritance.
You said
I read that in virtual inheritance, constructors are called "from the most derived".
That is true. Let me elaborate.
In your case, D is the most derived.
When you construct an instance of D, the constructors for A is called from the constructor of D since there is only instance of A for each instance of D. Constructor for A will not be called from the constructor of B or C.
When you construct an instance of B, then constructor for A is called from the constructor of B. Similarly for an instance of C.
If you had a sub-type of D,
struct E : public D
{
};
and you create an instance of E, then the constructor of A will be called from the constructor of E.
The C++ Draft Standard (N3337) says this about initialization involving virtual base classes:
12.6.2 Initializing bases and members
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.
That is how objects are built.
UPDATE
Check this example out:
class A{
A()
{
cout << "Constructor A"<<endl;
}
~A()
{
cout << "Destructor A"<<endl;
}
}
class B : public A{
B()
{
cout << "Constructor B"<<endl;
}
~B()
{
cout << "Destructor B"<<endl;
}
}
class C : public B{
C()
{
cout << "Constructor C"<<endl;
}
~C()
{
cout << "Destructor C"<<endl;
}
}
Creating an object of class C:
C obj;
The output will be as follows:
Constructor A
Constructor B
Constructor C
Destructor C
Destructor B
Destructor A
The reason for the execution is this:
When a class derives from another class, it derives the properties of that class. Functionalities of the derived class may or may not depend on the functionalities of the base class, but it can never be the other way. Assuming the derived class depends on the base class functionalities, it is important that the base class is properly initialized before the derived class can be initialized.
UPDATE:
When an object of C is made, he control from C constructor is transferred to it's base class' constructor, before C's constructor can execute. That's what I meant by base class first.
UPDATE:
Your question can be best answered by drawing the object relationship.
We'll have A right on the top and D at the bottom.
"in virtual inheritance, [virtual base] constructors are called from the most derived" [type's constructor]. "
By the above statement, they're asking you to start from the most derived type's constructor (D) and transverse up to the most base class' (A) constructor.
UPDATE:
#leemes has made the execution flow clearer in the comments:
It is the constructor itself which "redirects" to the base's constructor. After this returns, it continues with its own constructor. What you miss is that what is written in curly braces is not the whole implementation. It's only what comes after the call to the base ctor and initializing the member variables. Same with ctor: You write in curly braces what is to be executed before calling the ctor of member variables and then the ctor of the base.