2015-04-30 16 views
7

wierzę nowoczesną C++ list initializer są bardzo przydatne do inicjalizacji obiektów, do tego stopnia, co eliminuje konieczność definiowania własnego konstruktora:Włącz domyślna lista Inicjator konstruktora

struct point 
{ 
    float coord[3]; 
}; 

point p = {1.f, 2.f, 3.f}; // nice ! 

Jednak to nie działa, gdy mój Klasa dziedziczy z innej klasy:

template<typename T> 
class serializable 
{ 
    protected: 
     serializable() = default; 
    ... 
    // other stuff 
} 

struct point : public serializable<point> 
{ 
    float coord[3]; 
}; 
point p = {1.f, 2.f, 3.f}; // Doesn't work :(

próbowałem dodanie point() = default; do mojej klasy punkt, ale to nie działało. Jak mogę jeszcze zainicjować punkt z listą inicjalizatora?

Odpowiedz

8

Pierwotny przypadek polegać łącznej inicjalizacji [dcl.init.list]:

Lista inicjalizacja obiektu lub odniesienia typu T jest zdefiniowany następująco:
...
- W przeciwnym razie Jeśli T jest agregatem, kruszywo inicjalizacji wykonuje się

Jeżeli agregat i kruszywa initialiazation są z [dcl.init.aggr] nacisk kopalni:

Agregat jest tablicą lub klasy (Rozdział 9) bez konstruktorów dostarczane przez użytkowników (12,1), nie prywatnych lub chronione niż składowe statyczne (punkt 11) nie klas bazowych (punkt 10) i bez funkcji wirtualnych (10.3).

Gdy agregacja jest inicjowana przez listę inicjalizującą, jak określono w 8.5.4, elementy listy inicjalizacyjnej są traktowane jako inicjalizatory dla członków agregatu, w rosnącym indeksie dolnym lub członowym. Każdy element jest inicjowany podczas kopiowania z odpowiedniej klauzuli inicjalizującej.

Ale teraz, ponieważ point posiada klasę bazową (serializable<point>) point nie jest agregatem i nie obsługuje już zagregowanego inicjalizacji.

Rozwiązaniem jest po prostu zapewnienie takiego konstruktora aby zainicjować point:

struct point : public serializable<point> 
{ 
    template <typename... T> 
    point(T... ts) 
    : coord{ts...} 
    { } 

    float coord[3]; 
}; 
+0

podziękować za ciebie jasnych i szczegółowych odpowiedzi. To juste sprawia, że ​​zastanawiam się, dlaczego standart jest taki. Zgaduję, że to dlatego, że konstruktory nie byłyby inaczej nazywane ... i może w niektórych przypadkach mogą być conflits między konstruktorami i inicjowanie listy. Jednakże, podobnie jak wszystkie konstruktory są '= default', które nie powinny powodować żadnego problemu – Amxx

+0

@Amxx Co jeśli klasy bazowe miały członków? A co, jeśli członkowie ci byliby domyślni? Nie jest jasne, co należy robić we wszystkich tych przypadkach - więc standard nie chce zgadywać. – Barry

+0

Możesz także spakować swoje dane do elementu lub klasy bazowej, na przykład 'struct point_data {float coord [3]; } ', a następnie" doskonały konstruktor przekazujący ", który opiera się na' {}. – Yakk

Powiązane problemy