为何基类构造函数可通过花括号调用却无法通过圆括号调用?
继承类构造函数调用差异的原因解析
先看示例代码:
struct Base { Base(int x) : x_{x} {} int get() { return x_; } private: int x_ = 0; }; struct Derived : Base {}; int main() { Derived d{5}; // Works fine std::cout << d.get() << std::endl; Derived dd(5); // Won't work std::cout << dd.get() << std::endl; }
核心原因拆解
列表初始化(花括号
{})的标准规则Derived属于C++标准定义的聚合类型:没有用户声明的构造函数、没有私有/保护的非静态数据成员、没有虚函数、没有基类构造函数的继承声明等。对于聚合类型的列表初始化,标准允许直接将初始化参数传递给基类的构造函数,完成基类部分的初始化,因此Derived d{5};可以正常编译。直接初始化(圆括号
())的标准规则
直接初始化不会触发聚合类型的特殊初始化逻辑。由于Derived没有显式通过using Base::Base;引入基类的构造函数,编译器无法找到接受int参数的Derived构造函数,因此Derived dd(5);在符合标准的编译器(如GCC、Clang)中会报错。MSVC的非标准扩展
MSVC默认开启了一项非标准的编译器扩展,允许在直接初始化聚合派生类时,隐式将参数传递给基类的构造函数,这相当于绕过了标准中对直接初始化的限制,所以这段代码在MSVC中可以正常运行,但这并不是C++标准的规定。
内容的提问来源于stack exchange,提问作者Kaiyakha
相关产品推荐
相关产品推荐

