“中产阶级"指的是“中产阶级".在使用非默认虚拟基础构造函数的Diamond继承图中:为什么它不是编译错误? [英] "Middle classes" in diamond inheritance graph using non-default virtual base constructor: why is it not a compile error?

查看:63
本文介绍了“中产阶级"指的是“中产阶级".在使用非默认虚拟基础构造函数的Diamond继承图中:为什么它不是编译错误?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

考虑菱形继承图(即虚拟基类).我们从上一个知道

Consider a diamond inheritance graph (i.e., virtual base class). We know from previous questions that on construction the most derived class directly calls the default (0-arg) constructor of the (virtual) base.

但是我们也从上一个问题的答案中知道(例如,此处如果菱形中的中间"类具有最派生类使用的构造函数,并且这些构造函数(通过初始化列表)调用"其(虚拟)基类的非默认构造函数,则为不被尊重……尽管中间"类的构造函数 的主体是被执行的.

But we also know from answers to the previous question (e.g., here that if the "middle" classes in the diamond have constructors that are used by the most-derived class and those constructors "call" non-default constructors of their (virtual) base class (via the initialization list) then that is not respected … though the bodies of the "middle" classes' constructors are executed.

那是为什么?我本以为应该是编译错误.(当然,当声明了最派生的类并创建了菱形时,就将其检测出来.)

Why is that? I would have thought it should be a compile error. (Detected, of course, when the most-derived class is declared and the diamond is created.)

我正在寻找两件事:

  • 此标准在哪里指定?
  • 这种显式但尚未被忽略的代码会在语言的其他地方发生吗?

我正在谈论的代码示例遵循其实际和预期的输出,如下所示:

Code sample of what I'm talking about follows its actual and expected outputs below:

B 0arg-ctor
Mf 0arg-ctor
Mt 0arg-ctor
useD

预期输出:

ERROR: (line 19) struct `D` creates a diamond inheritance graph where an explicitly
    written invocation of a virtual base class constructor is ignored (for base 
    classes `Mf`and `Mt` and ancestor virtual base class `B`

代码:

#include <iostream>
using namespace std;

struct B {
    B() noexcept { cout << "B 0arg-ctor" << endl; };
    B(bool) noexcept { cout << "B 1arg-ctor" << endl; };
};

struct Mf : public virtual B
{
    Mf() : B(false) { cout << "Mf 0arg-ctor" << endl; }
};

struct Mt : public virtual B
{
    Mt() : B(true) { cout << "Mt 0arg-ctor" << endl; }
};

struct D : public Mf, public Mt { };

void useD(D) { cout << "useD" << endl; }

int main()
{
    D d;
    useD(d);
    return 0;
}

推荐答案

在代码库中添加新类不会导致格式正确的类突然失效.那将是一场语言灾难.如果 Derived 初始化其虚拟基数 Base ,并且它是正确的代码,则存在进一步派生的类应该对没有影响.衍生的有效性.您的期望几乎会完全排除任何类的继承,这仅仅是因为它碰巧在某个地方使用了虚拟继承,并使虚拟继承无法使用.

Adding a new class to a codebase should not cause well-formed classes to suddenly become invalid. That would be a language disaster. If Derived initializes its virtual base Base, and it is correct code, then the existence of a further-derived class should have no impact on the validity of Derived. Your expectation would almost completely preclude inheritance from any class simply because it happens to use virtual inheritance somewhere, and make virtual inheritance unusable.

但是对于您要求的引文(来自n4762草案):

But for the citations you requested (from draft n4762):

10.9.2/13:

10.9.2/13:

在非委托构造函数中,初始化按以下顺序进行:—首先,,并且仅适用于派生程度最大的类(6.6.2),将虚拟基类按照它们在有向对象的深度优先从左到右遍历时出现的顺序进行初始化基类的非循环图,其中从左到右"是基类在派生类base-specifier-list中的出现顺序.

In a non-delegating constructor, initialization proceeds in the following order: — First, and only for the constructor of the most derived class (6.6.2), 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.

在第二部分中,您要询问的第二部分是在10.9.2/7中描述的非最基本派生类中的虚拟基础初始化程序:

And the second part you asked about, the virtual base initializer in a non-most-derived class is described here, in 10.9.2/7:

其中mem-initializer-id表示虚拟基类的mem-initializer在执行不是最派生类的任何类的构造函数时会被忽略.

这篇关于“中产阶级"指的是“中产阶级".在使用非默认虚拟基础构造函数的Diamond继承图中:为什么它不是编译错误?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆