举个简单的例子。
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()
构造函数,上面的代码应该很乐意编译。
编辑:我的不好,我链接的页面告诉了相反的故事。所以似乎铿锵有回归。
然而,我尝试过的所有版本的gcc都失败了,抱怨Derived
没有默认构造函数,而clang做得很好,但仅限版本3.9.0 ; g ++ - 7 段错误,甚至 1 。
你可以在godbolt上看到它。
那么,谁在这里有过错? Clang允许它,或gcc(禁止段错误)不允许它?
1 虽然它似乎仅在godbolt上这样做,但我无法在本地重现段错误。
答案 0 :(得分:3)
首先,编译器段错误始终是编译器错误。你应该举报。
其次,默认构造函数永远不会被继承。从N3242(N3797中的措辞类似),[class.inhctor]:
对于继承构造函数的候选集中的每个非模板构造函数,除了没有参数的构造函数或具有单个参数的复制/移动构造函数之外,构造函数使用相同的构造函数隐式声明除非在出现using声明的类中有一个用户声明的构造函数具有相同的签名。
Base
的默认构造函数未继承到Derived
,因此Derived t
应该是格式错误的,因为没有有效的构造函数接受零参数。
在C ++ 17中,尽管措辞不同,但这仍然是不正确的。仍然是[class.inhctor],来自N4618:
当调用类型B的构造函数来初始化不同类型D的对象时(也就是说,当构造函数被继承时(7.3.3)),初始化就像使用默认的默认构造函数初始化D一样进行对象和继承构造函数的每个基类子对象,除了 通过调用继承的构造函数初始化B子对象。
要调用Base::Base()
,我们必须从Derived::Derived()
开始。但是没有Derived::Derived()
。