为什么需要 super class 空构造函数但在可怕的钻石情况下不调用?

Why is super class empty constructor required but not called in a dreaded diamond situation?

我正在尝试实现以下设计,这是一种dreaded diamond情况:

struct super_base
{
  super_base(int a) { b = a; }
  int b;
};

struct base : virtual super_base
{};

struct other_base : virtual super_base
{};

struct derived : base, other_base
{
  derived(int a) : super_base{a} {}
};

int main() {}

这是行不通的。上述代码使用 Clang 的错误相当多 善于解释错误:

error: call to implicitly-deleted default constructor of 'base'
  derived(int a) : super_base{a} {}
  ^
note: default constructor of 'base' is implicitly deleted because base
      class 'super_base' has no default constructor

所以我为 super_base 添加了一个空构造函数,它起作用了:

#include<iostream>
#include<stdexcept>

struct super_base
{
  super_base() { throw std::logic_error{"Constructor should not be called."}; };
  super_base(int a) { b = a; }
  int b;
};

struct base : virtual super_base
{};

struct other_base : virtual super_base
{};

struct derived : base, other_base
{
  derived(int a) : super_base{a} {}
};

int main() { std::cout << derived(10).b << '\n'; }

但是为什么不抛出呢?

P.S.: 我故意使用了一个可怕的菱形模式来说明虚拟继承的使用。单继承问题依然存在。

P.P.S.: 使用的编译器是Clang 3.9.1。结果与 海湾合作委员会 6.3.1.

struct base:super_base {}:

这会尝试创建一些构造函数。它试图创建的其中之一是 base::base().

如果super_base没有super_base::super_base(),则删除该构造函数

如果我们有 super_base::super_base()=default{},那么默认情况下 base::base() 存在,即使您没有 =default

同样的事情发生在other_base

并且您的派生 class 尝试调用已删除的基础对象构造函数,这会给您带来错误。

现在,为什么不叫它呢?当你有一个虚拟基础 class 时,构造函数只被调用一次。调用虚拟基础 classes 构造函数的中间类型将忽略它们的调用。

所以我们 derived() 调用 base()base() 调用 super_base(),但由于虚拟继承,该调用被忽略。

改为使用

derived() 调用 super_base(int)

现在,为什么要制定这些规则?因为C++没有"constructor that can only be called if you are a derived class of this class explicitly calling a specific base constructor"的概念。虚拟继承并不像您想要的那样功能齐全。