简体   繁体   中英

Complicated Order of construction - involving virtual inheritance

I came across this question which has me confused.

The code for this is :

  struct B1 { B1(){std::cout << "B1\n";} };
  struct V1 : public B1 {  V1(){std::cout << "V1\n";} };
  struct D1 : virtual public V1 {D1(){std::cout << "D1\n";} };

  struct B2 {B2(){std::cout << "B2\n";} };
  struct B3 {B3(){std::cout << "B3\n";} };
  struct V2 : public B1, public B2 {V2(){std::cout << "V2\n";} };
  struct D2 : public B3, virtual public V2 {D2(){std::cout << "D2\n";} };
  struct X : public D1, public D2 { };

Question : What is the order of construction of X ?

Here is a diagram that i constructed with the aim of simplifying it

在此处输入图片说明

First I would like to answer this question with the fact considering there is no virtual inheritance. The keyword virtual is replaced by public I would get

B1,V1,D1, [B3,B1,B2,V2,D2] , X

However I am not sure how I would approach this question when virtual inheritance comes along. The code as it is mentioned. I read that it is solved exactly the same except that virtual bases are given precedence. Which are the virtual bases here ? Any suggestions on how to tackle such a problem ?

Here's the rule (§12.6.2 [class.base.init]/p11):

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, if V1 and V2 are virtual bases, then the construction goes V1 -> V2 -> D1 -> D2 -> X's compound statement. V1's constructor will construct a B1 first, then execute its body. V2's constructor will construct a B1 and a B2, then execute its body. D2's constructor will construct a B3 before executing its body. (Because neither D1 nor D2 is the most derived class, their constructors don't construct the virtual bases V1 or V2.) Hence the overall printout order is B1 -> V1 -> B1 -> B2 -> V2 -> D1 -> B3 -> D2 -> X.

If V1 and V2 aren't virtual bases, then X's constructions is simply D1 -> D2 -> X. D1 has a single direct base V1, V1 has a single direct base B1, so you get B1 -> V1 -> D1 for the first part. Similarly, you construct B3 -> B1 -> B2 -> V2 -> D2 for the second part, so the overall order is B1 -> V1 -> D1 -> B3 -> B1 -> B2 -> V2 -> D2 -> X.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM