Reputation: 4581
I have this C++ code:
class BaseClass {
int id;
public:
BaseClass() { printf("BaseClass()\n"); }
virtual ~BaseClass() { printf("~BaseClass()\n"); }
};
class Class1 : public BaseClass
{
int id;
public:
Class1() { printf("Class1()\n"); }
~Class1() { printf("~Class1()\n"); }
};
class Class2 : public Class1
{
BaseClass id;
public:
Class2() { printf("Class2()\n"); }
~Class2() { printf("~Class2()\n"); }
};
class Class3 : virtual public BaseClass
{
int id;
public:
Class3() { printf("Class3()\n"); }
~Class3() { printf("~Class3()\n"); }
};
class Class4 : public Class3, virtual public Class1
{
Class3 id;
public:
Class4() { printf("Class4()\n"); }
~Class4() { printf("~Class4()\n"); }
};
int main(int argc, char* argv[])
{
BaseClass *p = new Class2;
Class2 *p1 = new Class2;
Class3 *p2 = new Class3;
delete p;
delete p1;
delete p2;
return 0;
}
This is the output:
BaseClass()
Class1()
BaseClass()
Class2()
BaseClass()
Class1()
BaseClass()
Class2()
BaseClass()
Class3()
~Class2()
~BaseClass()
~Class1()
~BaseClass()
~Class2()
~BaseClass()
~Class1()
~BaseClass()
~Class3()
~BaseClass()
and I don't understand why. I would expect that the output is the following:
BaseClass()
Class1()
Class2()
BaseClass()
Class1()
Class2()
...
etc.
Why isn't Class2()
printed after Class1()
when creating, for example, p1
?
Does this have something to do with virtual inheritance?
Upvotes: 2
Views: 81
Reputation: 173044
Why isn't Class2() printed after Class1() when creating, for example, p1?
Because Class2
has a non-static member object with type BaseClass
, its ctor will be called before the ctor of Class2
.
According to the initialization order:
Initialization order
1) If the constructor is for the most-derived class, virtual base classes are initialized in the order in which they appear in depth-first left-to-right traversal of the base class declarations (left-to-right refers to the appearance in base-specifier lists)
2) Then, direct base classes are initialized in left-to-right order as they appear in this class's base-specifier list
3) Then, non-static data members are initialized in order of declaration in the class definition.
4) Finally, the body of the constructor is executed
For new Class2;
, the direct base class Class1
and its base class BaseClass
will be invoked firstly. And then the non-static data member id
with type BaseClass
will be invoked. And the body of ctor of Class2
will be invoked at last. So you'll get
BaseClass()
Class1()
BaseClass()
Class2()
Upvotes: 3
Reputation: 118445
Let's go step by step with the first object being constructed:
new Class2;
This is the first object you're contructing, let's called it p
.
BaseClass()
p
's BaseClass
.
Class1()
p
's Class1
, the subclass of BaseClass
gets constructed.
BaseClass()
This is the id
member of Class2
being constructed.
Class2()
And now, finally, Class2
, p
itself.
So, despite your belief otherwise, Class2()
is printed after Class1()
. Except that you forgot that Class2
also has an id
member, that's a BaseClass
, and which must also be constructed before the Class2::Class2()
constructor gets invoked. You believed that you were seeing the second new
ed object's BaseClass
being constructed, but what was really getting constructed was the BaseClass
member object.
P.S. This is C++
. In C++
we use std::cout
instead of printf
(). printf()
is so ...last century.
Upvotes: 2