[英]Designated initializers in C++20
我有一个关于 c++20 功能的问题,指定初始化程序(有关此功能的更多信息,请点击此处)
#include <iostream>
constexpr unsigned DEFAULT_SALARY {10000};
struct Person
{
std::string name{};
std::string surname{};
unsigned age{};
};
struct Employee : Person
{
unsigned salary{DEFAULT_SALARY};
};
int main()
{
std::cout << std::boolalpha << std::is_aggregate_v<Person> << '\n'; // true is printed
std::cout << std::boolalpha << std::is_aggregate_v<Employee> << '\n'; // true is printed
Person p{.name{"John"}, .surname{"Wick"}, .age{40}}; // it's ok
Employee e1{.name{"John"}, .surname{"Wick"}, .age{40}, .salary{50000}}; // doesn't compile, WHY ?
// For e2 compiler prints a warning "missing initializer for member 'Employee::<anonymous>' [-Wmissing-field-initializers]"
Employee e2 {.salary{55000}};
}
此代码使用 gcc 9.2.0 和-Wall -Wextra -std=gnu++2a
标志编译。
正如您在上面看到的,结构体Person
和Employee
都是聚合,但是使用指定的初始化程序无法初始化Employee
聚合。
有人可以解释我为什么吗?
根据 C++ 20 标准(9.3.1 聚合。第 #3 页)
(3.1) — 如果初始化器列表是指定初始化器列表,则聚合应为 class 类型,每个指示符中的标识符应命名 class 的直接非静态数据成员,以及聚合的显式初始化元素是属于或包含这些成员的元素。
所以你不能使用指定的初始化列表来初始化基类的数据成员。
改用通常的列表初始化,例如
Employee e1{ "John", "Wick", 40, 50000 };
或者
Employee e1{ { "John", "Wick", 40 }, 50000 };
或者正如@Jarod42在评论中指出的那样,你可以写
Employee e1{ { .name{"John"}, .surname{"Wick"}, .age{40} }, 50000 };
在这种情况下,直接基数 class 由指定的初始化程序列表初始化,而 class Employe 整体由非指定的初始化程序列表初始化。
您可能有来自不同基础的多个具有相同名称的字段,
所以从逻辑上讲,您应该提供所需基地的名称,但似乎没有办法做到这一点。
// Invalid too:
Employee e1{.Person.name{"John"}, .Person.surname{"Wick"}, .Person.age{40}, .salary{50000}};
Employee e2{.Person{.name{"John"}, .surname{"Wick"}, .age{40}}, .salary{50000}};
另外 C++ 指定的初始化比 C 更受约束:
注意:乱序指定初始化、嵌套指定初始化、指定初始化和正则初始化混合、arrays的指定初始化在C编程语言中都支持,但在ZF6F87C9FDCF18B3C2C9Z877F中不允许。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.