I have always thought that base class constructors/destructors/friends are not inherited by derived class. This link confirms this :
http://www.geeksforgeeks.org/g-fact-4/.
I was also aware that we can write base class constructors in the initialization list of derived class initializer list.
Having said that: I tried to check my skills today about it. But I failed to guess the output of this program.
#include<iostream>
class A {
int x, y;
public:
A(int a = 0, int b = 0) : x(a), y(b) {
std::cout << "A ctor called" << std::endl;
}
void print_A() {
std::cout << "x = " << x << std::endl;
std::cout << "y = " << y << std::endl;
}
};
class B : public A {
int z;
public:
// I knew that A member can be initilized like this.
B(int a = 0, int b = 0, int c = 0) : z(a), A(b, c) {
std::cout << "C ctor called" << std::endl;
// I was not aware about that.
A(b, c);
}
void print_B() {
std::cout << "z = " << z << std::endl;
}
};
int main() {
B b(1, 2, 3);
b.print_A();
b.print_B();
}
Output :
A ctor called
C ctor called
A ctor called
x = 2
y = 3
z = 1
Couple of questions:
If constructors/desctructors/friends are not inherited from base, how can class 'B' is able to access constructor of class 'A' here.
How come you get this output? How come two constructors of 'A' have been called.
Your understanding is faulty. This:
// I was not aware about that.
A(b, c);
doesnt initialise the A member of B, it (notionally at least) creates a temporary, nameless local variable in the body of the constructor, somewhat analogous to if you had said:
A a(b, c);
The constructor for A is a public member, so anything can call it.
If constructors/desctructors/friends are not inherited from base, how can class 'B' is able to access constructor of class 'A' here?
"Not inherited" does not mean "inaccessible to the derived class". A derived class can certainly reference a base constructor. B's constructor does it twice:
The first access is in the initialization list
The second access is in the body of B's constructor; it creates a temporary object
Inheriting a constructor would mean that users of B would be able to access B(int, int), which they cannot do*.
It seems like a constructor call. Why does it create a temporary object?
Consider this method:
void foo(const A& a);
A common way is to call it like this:
A a(1, 2);
foo(a);
but C++ also lets you call it without creating A on a separate line:
foo(A(1, 2));
In this case C++ creates a temporary object, and passes foo a reference to it. When you write
A(1, 2)
C++ also creates a temporary object for you by calling its constructor.
How come two constructors of 'A' have been called.
The constructor is invoked twice; that is why you get the output.
* C++11's using mechanism allows you to achieve an effect very similar to constructor inheritance, provided that you follow specific rules.
the constructor is called by the every time A(b, c) is called;
you are calling it on line
B(int a = 0, int b = 0, int c = 0) : z(a), A(b, c) {
and you are calling it inside the b constructor
// I was not aware about that.
A(b, c);
the code works as intended
If constructors/desctructors/friends are not inherited from base, how can class 'B' is able to access constructor of class 'A' here.
You mean on these lines?
// I was not aware about that.
A(b, c);
It isn't "accessing the constructor" in the sense you think. It just creates (and immediately discards) an anonymous temporary A in the body of the constructor function.
How come you get this output? How come two constructors of 'A' have been called.
Because you created two instances of A: the base-class subobject of B b, and the anonymous temporary.
Here's an easy experiment to verify this, with the following logging:
// in A
A(int a = 0, int b = 0) : x(a), y(b) {
std::cout << "A::A #" << static_cast<void*>(this) << std::endl;
}
~A() {
std::cout << "A::~A #" << static_cast<void*>(this) << std::endl;
}
// in B
B(int a = 0, int b = 0, int c = 0) : z(a), A(b, c) {
std::cout << "B::B #" << static_cast<void*>(this) << std::endl;
A(b, c);
}
~B() {
std::cout << "B::~B #" << static_cast<void*>(this) << std::endl;
}
I get output something like
A::A #0xffec7054
B::B #0xffec7054
A::A #0xffec704c
A::~A #0xffec704c
x = 2
y = 3
z = 1
B::~B #0xffec7054
A::~A #0xffec7054
See that the instance address of the second A::A is different from the first (so it's a different object), and it's followed by an A::~A (because the anonymous temporary goes immediately out of scope).
Notes:
If you could "call the constructor" as you suggested originally, it would look something like
auto subobject = static_cast<A*>(this);
new (subobject) A(b, c);
and would be very wrong. The A subobject of b was completely constructed when it's own constructor completed, before the body of B's constructor starts. You can't just re-create a new object in the same space, what would happen to the old one?
This may seem trivial, but for objects with dynamically-allocated resources, it would be a serious bug. It's not allowed.
You wrote your initializer list : z(a), A(b, c), but should be aware the base-class subobject will be constructed before the derived-class members are initialized. That is, those two things will happen in the opposite order to what you wrote. It's not (necessarily) an error, but it's worth knowing.
Related
I was pretty sure the calling of B(A()) will call the defined constructor of B in my code.
But I was surprised to find out that it didn't call to my constructor B and of course didn't print "Constructor B".
So, to which constructor this code is calling (what is the signature of this constructor that it's calling to)?
struct A
{
};
struct B
{
B(const A a) { std::cout << "Constructor B" << std::endl; }
};
int main()
{
B(A());
return 0;
}
It doesn't construct an object with type B as you expected, then no constructor is called.
When declaring variables we can add (unnecessary) parentheses around the variable name, i.e. int (a); has the same effect as int a;. Similarly, B(A()); is same as B A();, which declares a function named A, which takes no parameters and returns B.
As the workaround you can change () to {}, e.g.
B(A{});
B{A()};
B{A{}};
LIVE
Consider the following code
#include <iostream>
using namespace std;
class A
{
int x;
public:
A() { cout << "A's constructor called " << endl; }
};
class B
{
public:
static A a;
B() { cout << "B's constructor called " << endl; }
static A getA() { return a; }
};
A B::a; // definition of a
int main()
{
B b1, b2, b3;
A a = b1.getA();
cout<<&a<<endl;
cout<<&B::a;
return 0;
}
the output is
A's constructor called
B's constructor called
B's constructor called
B's constructor called
0x7fff03081280
0x601194
Now lets consider another similar code
#include <iostream>
using namespace std;
class A
{
int x;
public:
A() { cout << "A's constructor called " << endl; }
};
class B
{
public:
static A a;
B() { cout << "B's constructor called " << endl; }
static A getA() { return a; }
};
A B::a; // definition of a
int main()
{
B b1, b2, b3;
A a ;
a= b1.getA();
cout<<&a<<endl;
cout<<&B::a;
return 0;
}
the output is
A's constructor called
B's constructor called
B's constructor called
B's constructor called
A's constructor called
0x7ffc485a1070
0x601194
Now my question is that why in the first case the constructor of A is called only once , whereas in the second code its called twice.
Also the two output &a and &B::a are different so it means they are two different objects .
Please explain why this is so.
In your first code
A a = b1.getA();
the copy-constructor of A gets called which doesn't generate any output. Define it yourself and you'll get a similar output to your second code.
Hmm, B::a is B's (public) static member instance of otherwise quite an usual class A. So, the first A's constructor logged is that of B::a, which should be initialized before control enters main, but next you create a separate instance of A local to main, it is constructed in order alongside with other main's local variables (here, right after all the Bs) and it is naturally distinct from B::a.
Now my question is that why in the first case the constructor of A is called only once , whereas in the second code its called twice.
Because in the first case you default-initialised only the static B::a, and copy-initialised the local a.
In the second you default-initialised both objects.
The crucial difference is that you only print a message in the default constructor, and don't print anything in the copy constructor.
Also the two output &a and &B::a are different so it means they are two different objects .
That is correct. a is a local variable, while B::a is a static member variable. They are different objects.
Static member variables of class type represent a storage with process-wide life span. It gets initialized as such, at some point before entry point to program - the beginning of main() - is reached. That's the first constructor call.
The line
A a = b1.getA();
initializes object a by calling copy constructor and through return value optimization and copy elision there is no default constructor call.
The second variant:
A a; // A() call
a = b1.getA(); // operator= call
Modified class
class A
{
int x;
public:
A(const A& a): x(a.x) { cout << "A's copy constructor called " << endl; }
A(A&& a): x(a.x) { a.x = 0; cout << "A's move constructor called " << endl; }
const A& operator=(const A& a) { x = a.x; cout << "A's copy operator= called " << endl; }
A() { cout << "A's constructor called " << endl; }
};
would give this output in first case:
A's constructor called
B's constructor called
B's constructor called
B's constructor called
A's copy constructor called
And second case would result in:
A's constructor called
B's constructor called
B's constructor called
B's constructor called
A's constructor called
A's copy constructor called
A's copy operator= called
It is simple to understand that whenever the class instance (object) getting created associated constructor is getting called.
Now my question is that why in the first case the constructor of A is called only once , whereas in the second code its called twice.
You are creating second object directly in stack and constructor is getting called in later case, first one is the static and second one by creating object in stack by below statement.
A a ;
In first case, instead of constructor, copy constructor is getting called so thats why you are not getting the print statement second time.
A a = b1.getA();
How the compiler do composition in inheritance?
suppose that I create an object of a derived class where both the base class and the derived class contain via composition object of other classes. I want some example to explain constructors and destructors.
I'm not going to make this overly easy for you, given it does indeed look like homework. If you can think through and understand what's below - good luck to you....
The base class's constructor is invoked, which will - for each member variable in order of declaration in the base class - call either the constructor corresponding to arguments specified in the base class initialisation list or the default constructor if any (otherwise the member's left uninitialised, though sometimes e.g. earlier zero-initalisation of the memory the object is contained in - perhaps due to new (p) T() notation or being static - will guarantee specific values anyway). Then, the derived constructor does the same for its own data members. Destruction happens in reverse order.
If you need to demonstrate the basic principles, you could use some variants of:
struct M { // Marker
int id;
M(int i) : id(i) { cout << "\tconstruction M" <<id<< endl; }
~M() { cout << "\tdestruction M" <<id<< endl; }
};
struct B { //Base
M mb;
B() : mb(1) { cout << "construction B (body finished)" << endl; }
~B() { cout << "destruction B (body finished)" << endl; }
};
struct D : public B { //Derived
M md;
D() : md(2) { cout << "construction D (body finished)" << endl; }
~D() { cout << "destruction D (body finished)" << endl; }
};
Of course, it's simplified, but it shows that the base is constructed before the derived, and members are constructed before constructore body is executed. It shows as well as that destruction is performed in reverse order of construction.
But that's only the most obvious. You should aslo show examples demonstrating in which order members are constructed when there are severals, and what happens in multiple inheritance, as well as the case of static members.
So I'm just getting caught up in some nuisances of C++. Specifically, passing anonymous variables by reference for use in an initializer list for a class in C++. Consider the following code;
class A {
public:
int x;
A(int x=0) : x(x) {
std::cout <<"A: creatred\n";
}
~A() {
std::cout << "A: destroyed\n";
}
};
class B {
public:
A a;
B(const A& in) : a(in) {
std::cout <<"B: creatred\n";
}
~B() {
std::cout << "B: destroyed\n";
}
};
int main() {
B b(A(0));
std::cout << "END\n";
return 0;
}
outputs:
A: creatred
B: creatred
A: destroyed
END
B: destroyed
A: destroyed
I count 2 creations and 3 destructions. What's going on? Way I see it, I'm using an anonymous variable A(0) as input when creating b. Not sure what the order of things are now. A reference to the anonymous variable is created and used to copy (the copy constructor will be called in the initializer list, yes?) the member variable a. When is the anonymous variable destroyed? And in general, why am I seeing 2 constructors called and 3 destructors. Thanks.
You didn't override A's copy constructor to print a message...
Specifically, a(in) invokes it.
The missing constructor would be the copy constructor for A.
You copy construct A in the below line.
B(const A& in) : a(in)
A: destroyed
END
This is the temporary being destroyed, it is destroyed at the end of the line
B b(A(0));
This question is very similar to this one Why can't I dynamic_cast "sideways" during multiple inheritence?, except that the cast does work - just not inside in the constructor.
Header:
class A
{
public:
virtual ~A() {}
void printA();
};
class B
{
public:
B();
virtual ~B() {}
void printB();
private:
std::string message_;
};
class C : public A, public B
{
public:
C() {}
virtual ~C() {}
};
Source:
void A::printA() { cout << "A" << endl; }
B::B()
{
A* a = dynamic_cast< A* >( this );
if ( a ) {
message_ = std::string( "A and B" );
} else {
message_ = std::string( "B" );
}
}
void B::printB() { cout << message_.c_str() << endl; }
Main:
int main( int argc, char* argv[] )
{
cout << "Printing C..." << endl;
C c;
c.printA();
c.printB();
cout << "Checking again..." << endl;
cout << !!dynamic_cast< A* >( &c ) << endl;
return EXIT_SUCCESS;
}
Result:
Printing C...
A
B
Checking again...
1
So, the dynamic_cast does work for multiple inheritance (no surprises there!), but why not when called at runtime for the 'this' pointer inside B::B()? I thought that the object was fully formed once inside the body of the constructor i.e. all the memory was allocated for the component objects, they haven't been initialised yet. I appreciate that this depends on the superclass constructor order, but in this example A is called before B.
I am obviously not understanding what exactly is happening under the hood, can someone please enlighten me?
Thanks,
Cam Bamber.
Basically the standard says it will not work (dynamic_cast) during construction of an object.
<quote>
Edit: Added based on VJo comment below.
Note: The cast from a 'B' to an 'A' using dynamic cast should work because we are casting an object of type 'C'. If we added the following code to main:
B bObj;
B& bRef = c;
B* bPtr = &c;
std::cout << !!dynamic_cast<A*>(&bObj) << std::endl;
std::cout << !!dynamic_cast<A*>(&bRef) << std::endl;
std::cout << !!dynamic_cast<A*>( bPtr) << std::endl;
The extra output would be:
0 // Can not convert a B to an A
1 // Can convert this B to an A because it is really a C.
1 // This is what we are reeling doing in B::B() that fails
// It is not the dynamic_cast<> that fails but the conversion of this from C* to B*
// That is causing UB
It fails in the constructor because the object is not fully formed. Using this we are trying to convert a C pointer into a B pointer before the C constructor has started (the code defined by the user). Thus the use of this in B::B() as a pointer to a C object fails thus when the dynamic_cast<> is called on this it fails to do what you want it to because of UB.
12.7 Construction and destruction [class.cdtor]
Paragraph 3
To explicitly or implicitly convert a pointer (a glvalue) referring to an object of class X to a pointer (reference) to a direct or indirect base class B of X, the construction of X and the construction of all of its direct or indirect bases that directly or indirectly derive from B shall have started and the destruction of these classes shall not have completed, otherwise the conversion results in undefined behavior. To form a pointer to (or access the value of) a direct non-static member of an object obj, the construction of obj shall have started and its destruction shall not have completed, otherwise the computation of the pointer value (or accessing the member value) results in undefined behavior.
[ Example:
struct A { };
struct B : virtual A { };
struct C : B { };
struct D : virtual A { D(A*); };
struct X { X(A*); };
struct E : C, D, X
{
E() : D(this), // undefined: upcast from E* to A*
// might use path E* → D* → A*
// but D is not constructed
// D((C*)this),
// defined:
// E* → C* defined because E() has started
// and C* → A* defined because
// C fully constructed
X(this) { // defined: upon construction of X,
// C/B/D/A sublattice is fully constructed
}
};
— end example ]
</quote>
Each base class constructor is executed before the derived class constructor, and during the B constructor, the dynamic type of the object is B; it does not become a C until you enter the C constructor. So you cannot do anything that requires a dynamic type of C: you can't cross-cast to any of Cs other base classes, and if you called a virtual function, then you would not get any overrides provided by C.
Under the hood, the dynamic type is (in most implementations at least) determined by a pointer in the object (known as the "vptr"), which points to some static data specifying properties of the class, including a table of virtual functions (known as the "vtable") and the information needed for dynamic_cast and typeid. Before each constructor, this is updated to point to the information for the class currently under construction.
During the construction of A then the dynamic type is A regardless. This is because you would start calling member functions of derived classes and accessing derived member variables before it's been constructed, which would be UB and very bad.
Since B doesn't inherit from A (B is parent-most class), the dynamic type of B during its constructor is B. Only when both the A and B parents are constructed can the child C be constructed, allowing for sideways dynamic_casting.
It doesn't work inside B, because B doesn't inherit from A