举一个简单的例子。
struct Base {
// Base::Base() defined by the compiler
};
struct Derived: Base {
using Base::Base; // Should inherit Base::Base()
Derived(int value):
m_value(value)
{}
private:
int m_value; // If Base::Base() is invoked, it's default constructed
};
Derived t;
根据我阅读cppreference的理解,Derived
应该继承默认的Base::Base()
构造函数,上面的代码应该可以愉快地编译
编辑:我的坏,我链接到的页面告诉完全相反的故事。看来clang已经回归了。
然而,我尝试过的所有版本的gcc都失败了,抱怨Derived
没有默认构造函数,而clang做得很好,但只是从3.9.0版本开始;g++-7分段故障,甚至1。
你可以自己在godbolt上看到它。
那么,谁的错在这里?为允许它而鼓掌,还是为不允许它而欢呼?
1尽管它似乎只在godbolt上这样做,但我无法在本地复制segfault。
首先,编译器segfault始终是一个编译器错误。你应该报告。
其次,默认构造函数永远不会被继承。根据N3242(N3797中的措辞类似),[class.inctor]:
对于继承构造函数的候选集合中的每个非模板构造函数,而不是没有参数的构造函数或具有单个参数的复制/移动构造函数,构造函数是用相同的构造函数特性隐式声明的,除非在出现using声明的类中存在具有相同签名的用户声明构造函数。
Base
的默认构造函数没有继承到Derived
中,因此Derived t
的格式应该不正确,因为没有接受零参数的有效构造函数。
在C++17中,尽管措辞不同,但这仍然是不正确的。Still[class.inctor],来自N4618:
当调用类型B的构造函数来初始化不同类型D的对象时(即,当继承构造函数时(7.3.3)),初始化过程就像使用默认默认构造函数来初始化D对象和继承构造函数的每个基类子对象一样,但通过调用继承的构造函数来初始化B子对象。
要调用Base::Base()
,我们必须从Derived::Derived()
开始。但没有Derived::Derived()
。