当我运行此代码时:
struct X {
int a;
};
struct Y : public X {};
X x = {0};
Y Y = {0};
我得到:
error: could not convert ‘{0}’ from ‘<brace-enclosed initializer list>’ to ‘Y’
为什么大括号初始化适用于基类而不适用于派生类?
原文由 Eric 发布,翻译遵循 CC BY-SA 4.0 许可协议
当我运行此代码时:
struct X {
int a;
};
struct Y : public X {};
X x = {0};
Y Y = {0};
我得到:
error: could not convert ‘{0}’ from ‘<brace-enclosed initializer list>’ to ‘Y’
为什么大括号初始化适用于基类而不适用于派生类?
原文由 Eric 发布,翻译遵循 CC BY-SA 4.0 许可协议
3 回答2k 阅读✓ 已解决
2 回答3.9k 阅读✓ 已解决
2 回答3.2k 阅读✓ 已解决
1 回答3.2k 阅读✓ 已解决
1 回答2.7k 阅读✓ 已解决
2 回答2.9k 阅读✓ 已解决
3 回答3.4k 阅读
C++ 17 之前的 C++ 标准版本的答案:
您的问题与 聚合初始化 有关:
struct X
是聚合,而struct Y
不是。这是关于聚合的标准报价(8.5.1):此子句指定如果
class
具有基类,则它不是聚合。在这里,struct Y
具有struct X
作为基类,因此不能是聚合类型。关于您遇到的特定问题,请从标准中获取以下条款:
当您执行
X x = {0}
时,聚合初始化用于将a
初始化为0
。但是,当您执行Y y = {0}
时,因为struct Y
不是聚合类型,编译器将寻找合适的构造函数。由于没有一个隐式生成的构造函数(默认、复制和移动)可以对单个整数执行任何操作,因此编译器会拒绝您的代码。关于此构造函数查找,来自 clang++ 的错误消息更明确地说明了编译器实际尝试执行的操作( 在线示例):
请注意,有 一个扩展聚合初始化以支持您的用例的提议, 并将 其纳入 C++17。如果我阅读正确,它会使您的示例在您期望的语义下有效。所以…您只需要等待符合 C++17 的编译器即可。