Es ist undefiniertes Verhalten. Laut [class.base.init]:
In einem nicht delegierenden Konstruktor wird die Initialisierung in der folgenden Reihenfolge ausgeführt:
- Zuerst und nur für den Konstruktor der am meisten abgeleiteten Klasse (1.8), virtuelle Basisklassen ...
- Dann werden direkte Basisklassen in der Deklarationsreihenfolge initialisiert, wie sie in der Basisspezifiziererliste erscheinen (unabhängig von der Reihenfolge der Mem-Initialisierer).
- Dann werden nicht statische Datenelemente in der Reihenfolge initialisiert, in der sie in der Klassendefinition deklariert wurden (wieder unabhängig von der Reihenfolge der Mem-Initialisierer).
b
wurde nicht initialisiert, wenn die Basisklasse A
initialisiert wurde. Die Zuweisung b = 0
ist selbst undefiniertes Verhalten aus dem gleichen Grund - b
wurde noch nicht initialisiert, als das aufgerufen wurde. Der Standardkonstruktor würde immer noch nach dem Konstruktor A
aufgerufen.
Wenn Sie sicherstellen möchten, dass b
zuerst initialisiert wird, ist der typische Ansatz Basis-von-Mitglied-Idiom :
In beiden Fällen ruft das Aufrufen einer Memberfunktion vor dem Initialisieren von Basisklassen undefiniertes Verhalten auf. §12.6.2 / 16:
Member-Funktionen (einschließlich virtueller Member-Funktionen, 10.3) können sein rief nach einem Objekt im Bau. In ähnlicher Weise ein Objekt unter Konstruktion kann der Operand des Operators
%Vor%typeid
(5.2.8) oder von a seindynamic_cast
(5.2.7). Wenn diese Vorgänge jedoch in a ausgeführt werden ctor-initializer (oder in einer Funktion, die direkt oder indirekt von einem ctor-Initialisierer aufgerufen wird) vor allen mem-Initialisierern Basisklassen sind abgeschlossen, das Ergebnis der Operation ist undefiniert. [Beispiel:
Allerdings ist der Zugriff und die Zuweisung zu b
selbst in Ordnung, da es eine leere Initialisierung hat und seine Lebensdauer beginnt, sobald Speicher dafür erworben wird (was lange vor dem Aufruf des Konstruktors passiert ist). Daher
ist gut definiert.
Tags und Links c++ constructor undefined-behavior clang++