Dlaczego muszę dodać A (...) na liście inicjalizatorów D'?
Dzieje się tak dlatego, że podobiekty baz wirtualnych muszą zostać zainicjowane przed wszystkimi innymi podobiektami. Ponieważ A
nie ma konstruktora domyślnego, należy jawnie zainicjować podobiekt wirtualny A
w D
i określić, z którego argumentu ma zostać zbudowany.
Po wykonaniu konstruktorów bazowych podobiektów B
i C
nie będą one miały obiektu podrzędnego A
w celu zainicjowania (co zostało wykonane wcześniej). Dlatego argumenty, które przechodzą do konstruktora A
, są nieistotne.
D(int x):B(x++), C(x++), A(x++){}
i D(int x):A(x++), B(x++), C(x++){}
obie dają ten sam wynik z cout<<D(10).x
, dlaczego?
Jak wyjaśniono powyżej, dzieje się tak, ponieważ wirtualne podstawowe obiekty podporządkowane są w pierwszej kolejności inicjowane.
Ogólnie kolejność inicjowania podobiektów klasy nigdy nie zależy od kolejności, w jakiej pojawiają się na liście inicjalizacyjnej konstruktora. Zgodnie z pkt 12.6.2/10 o C++ 11 Standard:
w nie-przekazaniu konstruktora inicjalizacji przebiega w następującej kolejności:
- Pierwszy, a tylko dla konstruktora najbardziej pochodne klasy (1.8), wirtualnych klas bazowych są inicjowane w w kolejności, w jakiej pojawiają się na pierwszym od lewej do prawej przewodzie skierowanego acyklicznego wykresu klas bazowych, , gdzie "od lewej do prawej" jest kolejnością pojawiania się klas bazowych na liście pochodnej klasy bazowej.
- Następnie klasy bazowe bezpośrednie są inicjowane w celu deklaracji, które pojawiają się w base-specyfikującego liście (niezależnie od kolejności MEM-inicjalizatorów).
- Potem non-statyczne 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).
- Na końcu złożona instrukcja ciała konstruktora jest wykonywana.