簡體   English   中英

C++20 中的指定初始化器

[英]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標志編譯。

正如您在上面看到的,結構體PersonEmployee都是聚合,但是使用指定的初始化程序無法初始化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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM