且构网

分享程序员开发的那些事...
且构网 - 分享程序员编程开发的那些事

使用具有虚拟多重继承的基本构造函数

更新时间:2023-09-13 15:15:04

这是一个相当常见的陷阱.首先,我要说 A 的出现是红色鲱鱼.您可以通过完全省略示例来简化示例.

This is a fairly common pitfall. First let me say that the presence of A is a red herring. You could have made your example shorter by omitting it entirely.

您看不到使用 B(int)的原因是由于C ++标准中的两个子句.首先 [class.inhctor]/8 说:>

The reason you don't see B(int) used is due to two clauses in the C++ standard. First [class.inhctor]/8 says:

隐式定义的继承构造函数执行以下操作的集合:用户编写的类的初始化带有mem-initializer-list的该类的内联构造函数只有mem-initializer具有用于命名基础的mem-initializer-id在using-declaration的nested-name-specifier中表示的类以及下面指定的表达式列表,其中函数主体中的复合语句为空([class.base.init]).

An implicitly-defined inheriting constructor performs the set of initializations of the class that would be performed by a user-written inline constructor for that class with a mem-initializer-list whose only mem-initializer has a mem-initializer-id that names the base class denoted in the nested-name-specifier of the using-declaration and an expression-list as specified below, and where the compound-statement in its function body is empty ([class.base.init]).

其中说,从 E 中的 D 继承的代码被翻译成如下形式:

Which says that the c'tor inherited from D in E is translated to something like this:

E::E(int i) : D(i) {}

不幸的是,这是您的问题.因为在咨询 [class.base.init/10] :

And that is unfortunately your problem. Because upon consulting [class.base.init/10]:

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

In a non-delegating constructor, initialization proceeds in the following order:

  • 首先,并且仅对于派生最多的类([intro.object])而言,虚拟基类按以下顺序初始化它们出现在定向的深度优先的从左到右的遍历中基类的非循环图,其中从左到右"是基类在派生类中的外观基本说明者列表.
  • First, and only for the constructor of the most derived class ([intro.object]), 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.

我们看到(强调我的意思),只有最派生的角色才能并且将初始化虚拟基础.以及最派生的c'tor是如何做到的?如我们先前所写.它从其成员初始化程序列表中省略了虚拟基础.因此,虚拟基础是默认初始化的.

We see (emphasis mine) that it is only the most derived c'tor that can and will initialize the virtual base. And how is the most derived c'tor doing that? As we wrote previously. It omits the virtual base from its member initializer list. So the virtual base is default initialized.

如果要将整数传递给 B 的字符.您需要自己定义 E 的构造函数:

If you want to pass an integer to B's c'tor. You need to define E's constructor yourself:

E::E(int i) : B(i), D(i) {}