How is the direct base built in virtual inheritance?

In the following code, I tried to create a Leaf obj object to see the constructor order in multi-layer inheritance, but I find the obj structure and constructor calls in this case a little strange.

 #include<iostream> using namespace std; class Base1 { public: Base1(void) { cout << "class Base1" << endl; } }; class Base2 { public: Base2(void) { cout << "class Base2" << endl; } }; class Level1 : public Base2, virtual public Base1 { public: Level1(void) { cout << "class Level1" << endl; } }; class Level2 : public Base2, virtual public Base1 { public: Level2(void) { cout << "class Level2" << endl; } }; class Leaf :virtual public Level2, virtual public Level1 { public: Leaf(void) { cout << "class Leaf" << endl; } }; int main(void) { Leaf obj; return 0; } 

With an output displaying constructor calls:

 class Base1 class Base2 clase Level2 class Base2 class Level1 class Leaf 

But the obj structure at the end of the program is actually:

 obj --Level2 ----Base2 ----Base1 --Level1 ----Base2 ----Base1 --Base1 

I know that Base1 of obj is virtual inherited, but when building obj it is also necessary to build Level2 and Level1 , which leads to Base1 in each of its members. But the whole build process only calls the Base1 constructor once. I can not explain it. Does this mean that Base1 in Level2 and Level1 inside obj shares the same data with Base1 , which directly belongs to obj ?

+5
source share
2 answers

But the whole build process only calls the Base1 constructor once. I can not explain it.

The explanation is that Base1 is the virtual base of all classes in the hierarchy. This is exactly what virtual databases are and what they are used for: sharing common instances of the base class.

Quotes from cppreference

For each individual base class that is indicated by a virtual one, the most derived object contains only one subobject of a base class of this type, even if the class appears repeatedly in the inheritance hierarchy (provided that it is inherited by the virtual each time).

All subobjects of virtual bases are initialized before any non-biblical subobject, so only the most derived class calls virtual database constructors in its list of initializers:

Given virtual inheritance, your block diagram can be considered as follows:

 obj --Level2 ----Base2 ----+-------Base1 --Level1 / / ----Base2 / / ----+----/ / --+-------/ 

Does this mean that Base1 in Level2 and Level1 inside obj uses the same data with Base1 that directly belongs to obj?

Yes. There is only one instance of Base1 in the entire obj structure.

+4
source

Does this mean that Base1 in Level2 and Level1 inside obj uses the same data with Base1 that directly belongs to obj?

Yes, there is only one subobject Base1 and is shared by the base subobject Level2 and Level1 in the Leaf class.

Here is an explanation with an example from the standard, $ 10.1 / 6 Several base classes [class.mi] (emphasized mine)

In another example

 class V { /* ... */ }; class A : virtual public V { /* ... */ }; class B : virtual public V { /* ... */ }; class C : public A, public B { /* ... */ }; 

for an object c type class c , one subobject of type V is equal , common to each base subobject c that has a virtual base class of type V Given the class c defined above, an object of class c will have one subobject of class V , as shown below.

+1
source

Source: https://habr.com/ru/post/1247214/


All Articles