c – 混合基类的虚拟和非虚拟继承

这是代码:

struct Biology
{    
    Biology() { cout << "Biology CTOR" << endl; }
};

struct Human : Biology
{    
    Human() { cout << "Human CTOR" << endl; }
};

struct Animal : virtual Biology
{
    Animal() { cout << "Animal CTOR" << endl; }
};

struct Centaur : Human, Animal
{
    Centaur() { cout << "Centaur CTOR" << endl; }
};

int main()
{   
   Centaur c;

   return 0;
}

此代码打印:

Biology CTOR
Biology CTOR
Human CTOR
Animal CTOR
Centaur CTOR

为什么?

由于我们创建了一个Centaur对象,我们从构建人类,动物和最终半人马(从较少的派生到最多派生)开始构建半人马座。

我们从人类开始:
人类从生物学中继承,所以我们首先称之为生物学的构建者。
现在人类的基础建设,我们终于可以构建人类本身了。
但是,生物学又重建了!

为什么?幕后发生了什么?

请注意,这是完全有意的离开动物从生物学几乎继承,同时,它也是故意离开人类非实际上从生物学继承。

我们以不正确的方式解决恐惧钻石:人类和动物都应该实际上继承生物学,使其成为可能。

我只是好奇。

另外,请看这段代码:

struct Biology
{    
    Biology() { cout << "Biology CTOR" << endl; }
};

struct Human : virtual Biology
{
    Human() { cout << "Human CTOR" << endl; }
};

struct Animal : Biology
{    
    Animal() { cout << "Animal CTOR" << endl; }
};

struct Centaur : Human, Animal
{
    Centaur() { cout << "Centaur CTOR" << endl; }
};

int main()
{   
   Centaur c;

   return 0;
}

在这里,我们有人类从生物学继承,而动物则是以“经典的方式”继承。

但这一次,输出是不同的:

Biology CTOR
Human CTOR
Biology CTOR
Animal CTOR
Centaur CTOR

这是因为半人马从人类开始,然后从动物继承。

如果顺序是倒数,我们将在以前的第一个例子中获得相同的结果 – 两个生物学实例被连续构造。

这是什么逻辑?

请尝试解释你的方式,我已经检查了大量的网站谈论这个。但没有一个似乎满足了我的要求。

从输出中可以清楚地看出,两个生物学对象被实例化。那是因为你只有一个继承虚拟。两个基类实例是可怕的钻石问题的模糊性的原因,解决方案是使(我们知道)生物虚拟的遗传。

层次结构的概述:

Biology  Biology
   |       |     # one and only one inheritance virtual
Human     Animal
    \     /
    Centaur

好的,让我们再次考虑这些规则来读取输出:

>基类在派生类之前构建。
>基类按照它们在基本说明符列表中的顺序进行构造。
>虚拟基类是由非最终派生类 – see this之前的非虚拟基类构建的。

第一输出 – 动物几乎从生物学继承:

Biology CTOR     # virtual base class inherited from Animal
Biology CTOR     # non-virtual base class of Human
Human CTOR       # Human itself
Animal CTOR      # Animal's virtual base class already constructed
Centaur CTOR

第二输出 – 人类几乎从生物学继承:

Biology CTOR     # virtual base class inherited from Human
Human CTOR       # Human's virtual base class already constructed
Biology CTOR     # non-virtual base class of Animal
Animal CTOR      # Animal itself
Centaur CTOR

更多内容丰富的标准段落([class.base.init] / 10):

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).

http://stackoverflow.com/questions/35314297/mixing-virtual-and-non-virtual-inheritance-of-a-base-class

本站文章除注明转载外,均为本站原创或编译
转载请明显位置注明出处:c – 混合基类的虚拟和非虚拟继承