Why must virtual base classes be constructed by the most derived class?

痞子三分冷 提交于 2019-11-27 09:12:56
Caleth

Because it avoids this:

class A {
public:
    A(int) {}
};

class B0: virtual public A {
public:
    B0(): A(0) {}
};

class B1: virtual public A {
public:
    B1(): A(1) {}
};

class C: public B0, public B1 {
public:
    C() {} // How is A constructed? A(0) from B0 or A(1) from B1?
};

Because in the class hierarchy having a virtually inherited base class, the base class would/may be shared by multiple classes (in diamond inheritance for example, where the same base class is inherited by multiple classes). It means, there would be only one copy of the virtually-inherited base class. It essentially means, the base class must be constructed first. It eventually means the derived class must instantiate the given base class.

For example:

class A;
class B1 : virtual A;
class B2 : virtual A;
class C: B1,B2 // A is shared, and would have one copy only.

I find this rule error-prone and cumbersome (but then, what part of multiple inheritance isn't?).

But the logically imposed order of construction must differ from the case of normal (non-virtual) inheritance. Consider Ajay's example, minus virtual:

class A;
class B1 : A;
class B2 : A;
class C: B1,B2

In this case for each C two As are constructed, one as part of B1's construction, the other one as part of B2's construction. The code of the B classes is responsible for that, and can do it. The order of events is:

Start C ctor
   Start B1 ctor
      A ctor (in B's ctor code)
   End B1 ctor
   Start B2 ctor
      A ctor (in B's ctor code)
   End B2 ctor
End C ctor

Now consider virtual inheritance in

class A;
class B1 : virtual A;
class B2 : virtual A;
class C: B1,B2 

One order of event is

Start C ctor
   Start B1 ctor
      // NO A ctor
   End B1 ctor
   Start B2 ctor
      // NO A ctor
   End B2 ctor

   A ctor // not B's code!
End C ctor

It's possible that A is constructed before B1 and B2, but that's irrelevant. The important thing is that A's construction is not happening during the construction of the other base classes. That code is simply not executed, and cannot be executed, because the virtually inherited base class sub-object of type A is part of and under the control of the most derived class which is not accessible from B1 and B2's code; indeed, the C is not even fully constructed at the point in time B1 or B2 are being constructed and could potentially attempt creating an A in a C.

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!