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

时间:2017-03-11 23:22:19

标签: c++ inheritance multiple-inheritance diamond-problem

我正在尝试实现以下设计,即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。结果与之相同 GCC 6.3.1。

1 个答案:

答案 0 :(得分:6)

"start": "set NODE_ENV=development && webpack-dev-server --open --config ./webpack/webpack.config.dev.js",

这会尝试创建一些构造函数。其中一个尝试创建的是struct base:super_base {}:

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

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

同样的事情发生在=default

你的派生类试图调用被删除的基础对象构造函数,这会给你一个错误。

现在,为什么不叫它?如果有虚拟基类,则只调用一次构造函数。调用虚拟基类构造函数的中间类型忽略了它们的调用。

我们other_base调用derived()base()调用base(),但由于虚拟继承而忽略该调用。

super_base()调用derived()代替。

现在,为什么这些规则?因为C ++没有“构造函数的概念,只有当你是这个类的派生类,显式地调用特定的基础构造函数时才能调用它”。虚拟继承并不像你想的那样功能齐全。