C++ 混合基类的虚拟继承和非虚拟继承

C++ 混合基类的虚拟继承和非虚拟继承,c++,inheritance,constructor,multiple-inheritance,virtual-inheritance,C++,Inheritance,Constructor,Multiple Inheritance,Virtual Inheritance,代码如下: struct Biology { Biology() { cout << "Biology CTOR" << endl; } }; struct Human : Biology { Human() { cout << "Human CTOR" << endl; } }; struct Animal : virtual Biology { Animal() { cout << "An

代码如下:

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;
}
为什么?

由于我们创建了一个
Centaur
对象,我们从构建
Centaur
开始,首先构建
Human
Animal
,最后构建
Centaur
(我们从派生程度较低的到派生程度最高的)

让我们从人类开始:
人类
继承自
生物学
,因此我们首先调用
生物学
的构造函数。 既然构建了
Human
的基类,我们就可以最终构建
Human
本身了。 但是相反,
生物学
又被构建了

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

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

我们用一种错误的方式解决了可怕的钻石问题:人类和动物实际上都应该继承生物学才能成功

我只是好奇

此外,请参见以下代码:

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  Biology
   |       |     # one and only one inheritance virtual
 Human   Animal
    \     /
    Centaur
好的,让我们再次阅读输出,记住以下规则:

  • 基类在派生类之前构造
  • 基类是按照它们在基说明符列表中出现的顺序构造的
  • 虚拟基类是由最派生的类在非虚拟基类之前构造的
第一个输出-
动物
虚拟
ly继承自
生物学

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
第二个输出-
人类
虚拟
ly继承自
生物学

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

在非委托构造函数中,初始化在 顺序如下:

-首先,并且仅适用于大多数 派生类(1.8),虚拟基类按以下顺序初始化 它们出现在定向对象从左到右的深度优先遍历上 基类的非循环图,其中“从左到右”是 派生类中基类的外观 基本说明符列表

-然后,在中初始化直接基类 在基本说明符列表中显示的声明顺序 (无论mem初始值设定人的顺序如何)


非虚拟继承是一种排他性关系,就像成员关系一样。一个类可以是给定完整对象中另一个类的非虚拟基类

这意味着类可以重写非虚拟基类的虚拟函数,而不会导致冲突或问题

构造函数还可以可靠地初始化非虚基

只有虚基可以是完整对象的许多间接基的直接基类。因为虚拟基类可以共享,所以重写器可能会冲突

构造函数可以尝试初始化ctor init列表中的虚拟基子对象,但如果该类是进一步派生的,则该部分ctor init列表将被忽略

  • 实际上从
    Biology
    继承的所有基类在它们之间共享一个
    Biology
    base实例
  • 所有从
    Biology
    非虚拟继承的基类都有
    Biology
    的一个实例

  • 每个类别中都有一个基本类,因此有一个由人类引入的
    生物学
    (原则上与其他人共享)和一个由动物引入的
    生物学
    (从未与任何其他基本类共享)。

    这个答案是金色的。谢谢;)多好的问题啊!谢谢你的回答,虽然一年后哈哈