为什么下面的代码没有编译?
#include <vector>
class Foo
{
public:
Foo()
{ }
virtual ~Foo()
{ }
std::vector<int> aVec;
};
Foo bar =
{
{ 1, 2, 3, 4, 5 }
};
以下代码编译:
#include <vector>
class Foo
{
public:
/*Foo()
{ }
virtual*/ ~Foo()
{ }
std::vector<int> aVec;
};
Foo bar =
{
{ 1, 2, 3, 4, 5 }
};
除了参考语言规则外,请详细说明这些规则背后的基本原理。
为什么构造函数和虚析构函数的存在会停止初始化?
答案 0 :(得分:5)
因为Foo
属于类类型,所以支撑的初始化列表被视为aggregate initialization。除其他外,这需要该类没有显式构造函数或虚拟成员:
聚合初始化是列表初始化的一种形式,其中 初始化聚合。聚合是以下类型之一:
类类型(通常是struct或union),它有......
没有私人或受保护的非静态数据成员
没有用户提供,继承或显式(自C ++ 17)构造函数(允许显式默认或删除构造函数)
- 没有虚拟,私有或受保护的基类
- 没有虚拟成员函数
- 默认成员初始值设定项
答案 1 :(得分:5)
您正在使用的列表初始化形式称为link。它用于聚合类型。类型作为聚合的要求之一是它没有用户提供的构造函数。
通过提供构造函数,编译器将尝试将列表初始化与定义的构造函数之一进行匹配。它更喜欢构造函数采用单aggregate initialization。由于您没有提供一个,它将尝试查找与您的初始化列表提供的参数匹配的构造函数。由于唯一的构造函数是不带参数的默认构造函数,因此找不到匹配项。
答案 2 :(得分:1)
Foo bar = { { 1, 2, 3, 4, 5 } };
是aggregate initialization。它仅为数组和“聚合”类类型定义。添加任何构造函数或虚拟成员意味着该类型不是聚合的。