为什么需要 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"的概念。虚拟继承并不像您想要的那样功能齐全。
我正在尝试实现以下设计,这是一种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"的概念。虚拟继承并不像您想要的那样功能齐全。