2013-08-28 15 views
21

Mam trudności ze znalezieniem haseł w Google dla tego.Inicjator elementu nie nazwał niestatycznego elementu danych lub klasy bazowej

struct a { 
    float m_x; 
    float m_z; 
public: 
    a(float x): m_x(x) {} 
}; 

class b : public a { 
    b(float z): m_z(z) {} 
}; 

Na brzękiem 3.2:

error: member initializer 'm_z' does not name a non-static data member or base class 
    b(float z): m_z(z) {} 
+0

Dlaczego? Nie zrobiłem jeszcze "diamentu zła dziedziczenia". @AndreyT zaakceptowana odpowiedź w tym pytaniu mówi, aby zrobić ctor bazowy. Mam jedno ... och. Chyba muszę wywoływać ctor klasy bazowej, a nie członka ctor. ok. –

+0

@WhozCraig: Nawet jeśli jest to wirtualna baza, nadal nie pozwala inicjować * pośrednich * członków. Wirtualne dziedziczenie może wymagać inicjalizacji pośrednich * baz *, ale nie członków. – AnT

+1

@Svenven Lu: Zaakceptowana odpowiedź mówi, że 'a :: m_z' można zainicjować tylko z listy inicjalizującej konstruktora' a'. Nie można go wymienić na liście inicjalizującej konstruktora b "b" (tak jak w twoim kodzie).Język na to nie pozwala. O to chodzi. To znaczy. musisz dodać kolejny parametr do konstruktora 'a' specyficznie dla 'm_z' (jak zrobiłeś dla' m_x') i przekazać początkową wartość z 'b' przez ten konstruktor. BTW, w powyższym kodzie musisz odwołać się do konstruktora 'a' z konstruktora' b'. W przeciwnym razie nie zostanie skompilowany, ponieważ nie masz domyślnego konstruktora w 'a'. – AnT

Odpowiedz

26

No nie można zainicjować członków klasy bazowej z listy inicjatora bezpośrednio. To dlatego, że kolejność inicjalizacji przebiega w ten sposób

C++ standardowe n3337 § 12.6.2/10

W nie przekazaniu konstruktora przechodzi inicjalizacji w następującej kolejności:

- Po pierwsze, i tylko dla konstruktora klasy pochodnej (1.8), wirtualne klasy bazowe są inicjowane w kolejności pojawiają się na pierwszym od prawej do lewej stronie skierowanym węższym wykresie c lasses, gdzie "od lewej do prawej" jest kolejność pojawiania się klas bazowych w klasie pochodnej na podstawie bazowej listy specyfikatorów.

- Następnie klasy bazowe bezpośrednie są inicjowane w deklaracji kolejności, w jakiej pojawiają się w base-specyfikującego liście (niezależnie od kolejności MEM-inicjalizatorów).

- Następnie, non-static członkowie danych są inicjowane w kolejności, w jakiej zostały zadeklarowane w definicji klasy (ponownie, niezależnie od kolejności MEM-inicjalizatorów ).

- Ostatecznie, instrukcja złożona korpusu konstruktora jest wykonywana.

[Uwaga: Kolejność deklaracji jest wymagana w celu zapewnienia, że ​​podobiekty bazowe i zostaną zniszczone w kolejności odwrotnej niż inicjalizacja . - koniec uwaga]

Tak można określić konstruktor w klasie bazowej (może to być zabezpieczony) i użyć że jeden na liście inicjalizacji klasy pochodnej (should be preferred) lub można przypisać do członka klasy bazowej w klasie pochodnej ctor ciało (różne zachowanie, inny efekt, a także mniej wydajne - przypisujesz do domyślnego zainicjowanego (już ma wartość) członka).

W pierwszym przypadku można napisać to w ten sposób:

struct A { 
    float m_x; 
    float m_z; 
    A(){} 
protected: 
    A(float x): m_x(x) {} 
}; 

class B : public A { 
public: 
    B(float z) : A(z) {} 
    // alternatively 
    // B(float z) { 
    //  m_x = z; 
    // } 
}; 

int main(){ 
    B b(1); 
    return 0; 
} 
Powiązane problemy