C ++ 20'de belirtilen başlatıcılar


25

Başlatıcılar olarak belirlenmiş c ++ 20 özelliğinden biriyle ilgili bir sorum var (bu özellik hakkında daha fazla bilgi burada )

#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}}; 
}

Bu kod gcc 9.2.0 ve -Wall -Wextra -std=gnu++2abayraklarla derlenmiştir .

Eğer, yukarıya bakın hem yapılar, gibi Personve Employeeagrega ama başlatma olan Employeeagrega belirlenmiş başlatıcıları kullanılarak mümkün değildir.

Birisi bana nedenini açıklayabilir mi?


struct Employee : public Person
Sorununuzu çözüp çözmediğini


@GSerg Tamam, iyi ... Bunu hiç düşünmedim, çünkü her zaman publicveya privateher seferinde kullanıyorum ... teşekkürler yine de
skratchi.at

tam hatan nedir?
skratchi.at

2
@ skratchi.at structs varsayılan olarak herkese açık olarak devralınır
idclev 463035818

Yanıtlar:


15

C ++ 20 Standardına göre (9.3.1 Agregalar. S. # 3)

(3.1) - Başlatıcı listesi, atanmış bir başlatıcı listesiyse, agrega sınıf tipinde olmalı, her bir belirleyicideki tanımlayıcı sınıfın doğrudan statik olmayan bir veri üyesini ve toplamın açıkça başlatılmış öğelerini adlandırmalıdır. bu üyeler olan veya içeren öğelerdir.

Bu nedenle, temel sınıfların veri üyelerini başlatmak için belirtilen başlatıcı listesini kullanamazsınız.

Bunun yerine normal liste başlatmayı aşağıdaki gibi kullanın:

Employee e1{ "John", "Wick", 40, 50000 };

veya

Employee e1{ { "John", "Wick", 40 }, 50000 };

veya @ Jarod42 bir yorumda işaret ettiği gibi yazabilirsiniz

Employee e1{ { .name{"John"}, .surname{"Wick"}, .age{40} }, 50000 };

Bu durumda, doğrudan temel sınıf, belirlenmiş bir başlatıcı listesi tarafından başlatılırken, tüm olarak Sınıf sınıfı, atanmamış bir başlatıcı listesi tarafından başlatılır.


3
veya bir karışımı: Employee e1{ { .name{"John"}, .surname{"Wick"}, .age{40} }, 50000 };.
Jarod42

@ Jarod42 Evet, derler.
Moskova'dan Vlad

5

Farklı adlardan aynı ada sahip birkaç alanınız olabilir,

mantıklı bir şekilde, istenen tabanın adını vermelisiniz, ancak bunu yapmanın bir yolu yok gibi görünüyor.

// 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}};

Ek olarak C ++ ile belirtilen başlatma, C'den daha kısıtlıdır:

Not: sıra dışı belirlenmiş başlatma, iç içe belirlenmiş başlatma, belirlenen başlangıç ​​ve düzenli başlatmaların karıştırılması ve belirlenen dizilerin başlatılması C programlama dilinde desteklenir, ancak C ++ 'da izin verilmez.

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.