问题描述
我不确定是否将其称为compose initialization
。基本上我想知道的是:
- 如何初始化
foo
中的对象main
- 这种初始化是否有一些规则,因为我发现有时会失败。
给出以下代码:
#include <iostream>
#include <string>
#include <vector>
class Base {
public:
std::string str_mem;
int int_val = 0;
};
class Bar {
public:
Bar() = default;
Bar(int val) : int_val(val) {
}
auto GetVal() {
return int_val;
}
private:
int int_val = 0;
};
class Foo : public Base {
public:
int mem_1;
int mem_2;
int mem_3;
std::string str_mem;
Bar class_mem;
auto print() {
printf("[%d,%d,%s,%d]\n",mem_1,mem_2,mem_3,str_mem.c_str(),class_mem.GetVal());
}
};
auto main(int argc,char** argv) -> int {
Foo foo{{"base1",2},1,2,3}; // How `foo` is constructed,any constructor get called?
foo.print();
Foo foo1{{"base2",3,"string",3};
foo1.print();
}
解决方法
这是aggregate initialization,Foo
是aggregate type。
每个
direct public base,(since C++17)
数组元素或非静态类成员,按照类定义中数组下标/外观的顺序,从初始化列表的相应子句中进行复制初始化。
鉴于Foo foo1{{"base2",2},1,2,3,"string",3};
,Base
的子对象是从{"base2",2}
初始化的(它也被聚合初始化),数据成员mem_1
是从{{1}初始化的},1
从mem_2
初始化,2
从mem_3
初始化,3
从str_mem
初始化(由"string"
的构造函数采用std::string
),const char*
从class_mem
初始化(由构造函数3
)。
鉴于Bar::Bar(int)
,前面的成员以与上述相同的方式初始化,除了Foo foo{{"base1",3};
和str_mem
是从空列表中初始化的,因此它们是默认的-初始化(通过其默认构造函数)。
如果初始化程序子句的数量少于成员
class_mem
的数量,或者初始化程序列表完全为空,则其余成员and bases (since C++17)
从空列表中复制and bases (since C++17)
,在遵循通常的列表初始化规则(该规则对具有默认构造函数的非类类型和非聚合类执行值初始化,并对聚合进行聚合初始化)。