我正在尝试实现以下设计,即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。
答案 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 ++没有“构造函数的概念,只有当你是这个类的派生类,显式地调用特定的基础构造函数时才能调用它”。虚拟继承并不像你想的那样功能齐全。