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;
}
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. –
@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
@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