지정된 초기화 프로그램 인 C ++ 20 기능 중 하나에 대한 질문이 있습니다 (이 기능에 대한 자세한 정보는 here ).
#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 집계, p. # 3)에 따름
(3.1) — 이니셜 라이저리스트가 지정된 이니셜 라이저리스트 인 경우 집계는 클래스 유형 이어야하고 각 지정자의 식별자 는 클래스 의 직접 비 정적 데이터 멤버의 이름을 명시해야하며 집계의 명시 적으로 초기화 된 요소는 해당 구성원이거나 포함하는 요소입니다.
따라서 지정된 초기화 목록을 사용하여 기본 클래스의 데이터 멤버를 초기화 할 수 없습니다.
대신 일반적인 목록 초기화를 사용하십시오.
Employee e1{ "John", "Wick", 40, 50000 };
또는
Employee e1{ { "John", "Wick", 40 }, 50000 };
또는 @ Jarod42 가 주석에서 지적한 것처럼 쓸 수 있습니다.
Employee e1{ { .name{"John"}, .surname{"Wick"}, .age{40} }, 50000 };
이 경우 직접 기본 클래스는 지정된 이니셜 라이저 목록으로 초기화되는 반면 전체 클래스 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보다 더 제한적입니다.
참고 : 순서가 지정된 지정 초기화, 중첩 된 지정 초기화, 지정된 이니셜 라이저 및 일반 이니셜 라이저의 혼합 및 지정된 배열의 초기화는 모두 C 프로그래밍 언어에서 지원되지만 C ++에서는 허용되지 않습니다.