[英]Mixing virtual and non-virtual inheritance of a base class
This is the code:这是代码:
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;
}
This code prints:此代码打印:
Biology CTOR
Biology CTOR
Human CTOR
Animal CTOR
Centaur CTOR
Why?为什么?
Since we create a Centaur
object, we start from building the Centaur
by constructing Human
, Animal
and finally Centaur
(we start from the less derived to the most derived).因为我们创建了一个
Centaur
对象,所以我们从构建Centaur
开始,构建Human
, Animal
,最后构建Centaur
(我们从较少派生到派生最多)。
Let's start from Human
: Human
inherits from Biology
, so we call Biology
's constructor first.让我们从
Human
开始: Human
继承了Biology
,所以我们先调用Biology
的构造函数。 Now that Human
's base class is constructed, we can finally construct the Human
itself.既然已经构建了
Human
的基类,我们终于可以构建Human
本身了。 But instead, Biology
gets constructed again!但相反,
Biology
再次被构建!
Why?为什么? What's happening behind the scenes?
幕后发生了什么?
Please note that it was completely intentional leaving Animal
inheriting virtually from Biology
and, at the same time, it was also intentional leaving Human
non-virtually inheriting from Biology
.请注意,这完全是故意让
Animal
虚拟继承Biology
,同时也是故意让Human
非虚拟继承Biology
。
We are solving the Dreaded Diamond in an incorrect way: both Human and Animal should virtually inherit Biology to make this work.我们正在以错误的方式解决可怕的钻石:人类和动物都应该实际上继承生物学来完成这项工作。
I'm just curious.我只是好奇。
Also, see this code:另外,请参阅此代码:
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;
}
Here we have Human
inheriting virtually from Biology
, while Animal
is set to inherit in the "classic way".在这里,我们将
Human
虚拟地从Biology
继承,而Animal
设置为以“经典方式”继承。
But this time, the output is different:但这一次,输出不同:
Biology CTOR
Human CTOR
Biology CTOR
Animal CTOR
Centaur CTOR
This because Centaur
inherits at first from Human
and then from Animal
.这是因为
Centaur
首先从Human
继承,然后从Animal
继承。
Had the order been the inverse, we'd have achieved the same result as before, in the first example - two Biology
instances being constructed in a row.如果顺序是相反的,我们将获得与之前相同的结果,在第一个示例中 - 连续构造两个
Biology
实例。
What's the logic of this?这是什么逻辑?
Please try to explain your way, I've already checked tons of websites speaking about this.请尝试解释你的方式,我已经检查了大量关于这个的网站。 But none seems to satisfy my request.
但似乎没有一个能满足我的要求。
It's clear from the output that two Biology
objects are instantiated .从输出中可以清楚地看出,两个
Biology
对象已被实例化。 That is because you've made only one inheritance virtual
.那是因为你只做了一个继承
virtual
。 Two base class instances is the cause of ambiguity in dreaded diamond problem and the solution is to make (as we know) both inheritances of Biology
virtual
.两个基类实例是可怕的菱形问题中歧义的原因,解决方案是(如我们所知)使
Biology
两个继承成为virtual
。
Recap of the hierarchy:层次结构回顾:
Biology Biology
| | # one and only one inheritance virtual
Human Animal
\ /
Centaur
Ok, let's read the output again with these rules in mind:好的,让我们记住这些规则再次阅读输出:
1st output - Animal
virtual
ly inherits from Biology
: 1输出-
Animal
virtual
从LY继承Biology
:
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
2nd output - Human
virtual
ly inherits from Biology
:第二个输出 -
Human
virtual
继承自Biology
:
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
More informative standard paragraph ( [class.base.init]/10
) :更多信息标准段落(
[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 .
— 首先,并且仅对于最派生类 (1.8) 的构造函数,虚拟基类按照它们出现在基类的有向无环图的深度优先从左到右遍历中出现的顺序进行初始化,其中“左-to-right” 是基类在派生类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 ).
— 然后,直接基类按照它们出现在base-specifier-list中的声明顺序进行初始化(无论mem-initializers的顺序如何)。
...
...
Non virtual inheritance is an exclusive relationship, like membership.非虚拟继承是一种排他关系,就像成员资格一样。 A class can be the non-virtual base class of one other class in a given complete object.
一个类可以是给定完整对象中另一个类的非虚拟基类。
This implies that a class can override virtual functions of a non virtual base class without causing conflicts or issues.这意味着一个类可以覆盖非虚基类的虚函数而不会引起冲突或问题。
A constructor can also initialize non virtual bases reliably.构造函数也可以可靠地初始化非虚拟基类。
Only virtual bases can be direct base classes of many indirect bases of a complete object.只有虚拟基类可以是一个完整对象的许多间接基类的直接基类。 Because a virtual base class can be shared, overriders can conflict.
由于可以共享虚拟基类,因此覆盖程序可能会发生冲突。
A constructor can try to initialize a virtual base subobject in the ctor-init-list, but if the class is further derived, that part of the ctor-init-list will be ignored.构造函数可以尝试初始化 ctor-init-list 中的虚拟基子对象,但如果进一步派生该类,则 ctor-init-list 的那部分将被忽略。
Biology
share one instance of Biology
base between them.Biology
虚拟继承的所有基类在它们之间共享一个Biology
基实例。Biology
have one instance each of Biology
.Biology
有一个实例每个Biology
。 You have one base in each category, therefore you have one instance of Biology
brought in by Human
(and in principle shared with others) and one instance brought in by Animal
(never shared with any other base class).您在每个类别中都有一个基础,因此您有一个由
Human
引入的Biology
实例(原则上与其他人共享)和一个由Animal
引入的实例(从未与任何其他基类共享)。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.