Reihenfolge der Berufung Basisklasse Konstruktor von der abgeleiteten Klasse die Initialisierung der Liste
struct B { int b1, b2; B(int, int); };
struct D : B {
int d1, d2;
//which is technically better ?
D (int i, int j, int k, int l) : B(i,j), d1(k), d2(l) {} //1st Base
//or
D (int i, int j, int k, int l) : d1(k), d2(l), B(i,j) {} //last Base
};
Oben ist nur pseudo-code. Im eigentlichen wollte ich wissen, dass der Reihenfolge der Aufruf Basiskonstruktor egal ?
Gibt es irgendwelche schlechte Verhaltensweisen (vor allem Ecke Fälle), verursacht durch alle Fälle ? Meine Frage ist mehr auf den technischen Aspekt und nicht auf coding-styles.
Du musst angemeldet sein, um einen Kommentar abzugeben.
Den Auftrag, Sie beziehen sich in Ihrer Frage nicht den "Orden der Aufruf Basiskonstruktor". In der Tat, Sie können nicht rufen Sie einen Konstruktor. Konstruktoren sind nicht kündbar durch den Benutzer. Nur für den compiler-Aufruf von Konstruktoren.
Was Sie tun können, ist zu angeben Initialisierungen. In diesem Fall (Konstruktor-Initialisierungsliste) geben Sie an-Initialisierungen für Teilobjekte von einem größeren Objekt. Die Reihenfolge, in der Sie angeben, diese Initialisierungen, spielt keine Rolle: der compiler-Aufruf der Konstruktoren in einer ganz bestimmten Reihenfolge definiert, die durch die language-Spezifikation, unabhängig von der Reihenfolge, in der Sie angeben, die Initialisierungen. Die Basisklasse Konstruktoren sind immer als erste (in der Reihenfolge in der die Basisklassen sind aufgelistet in der Klasse definition), dann die Konstruktoren der member-Subobjekte genannt werden (wieder in der Reihenfolge, in der diese Elemente aufgelistet, die in der definition der Klasse).
(Es gibt einige Besonderheiten, die in dieser Regel, wenn es um virtuelle Basisklassen, aber ich beschloss, nicht, um Sie hier.)
Wie für das schlechte Verhalten... natürlich gibt es ein potential für "schlechtes Verhalten" hier. Wenn Sie davon ausgehen, dass die Reihenfolge der Initialisierung richtet sich nach der Reihenfolge, die Sie in der Konstruktor-Initialisierungsliste, werden Sie wahrscheinlich irgendwann laufen Sie in eine unangenehme überraschung, wenn Sie entdecken, dass der compiler komplett ignoriert, die Reihenfolge und verwendet seine eigene (in der Reihenfolge der Anmeldung) statt. Zum Beispiel, der Autor dieser code
erwarten
a
werden erst initialisiert, undb
erhalten den ursprünglichen Wert von5
ausa
, aber in der Realität nicht passieren, dab
initialisiert wird, bevora
.Die Reihenfolge ist klar definiert. Es hängt nicht davon ab, wie Sie angeben, die Sie während initializtion.
Basisklassenkonstruktor
B
wird zuerst aufgerufen und dann die member-Variablen(d1
&d2
) in der Reihenfolge, in der Sie deklariert sind.Zu erklären, wird der Kommentar in @Andrey T die Antwort.
Die Reihenfolge der Aufruf der Basisklasse Konstruktoren ist auch definiert durch den standard und:
Den virtuellen Basis-Klasse
MyClass3
ist bevorzugt über Basis-KlasseMyClass2
.virtual
base-Kommentar in die Antwort ?virtual
Basisklassen, die von Ihnen abhängen. Bedenken Sie:struct A{}; struct B : virtual A {}; struct C: virtual A {}; struct D : A, B {};
. In diesem FallD
erstellenA
bevor Sie es bauen können entwederB
oderC
, weil beideB
undC
verlangen, dassA
konstruiert werden, bevor Sie sind. Anstatt entwederB
oderC
zu konstruieren, dieA
(die komplexe in komplexeren Situationen, wie wenn es auchstruct E : C, B {};
, die zusätzliche compilerB
immer KonstrukteA
, dannE
hätte UB, mit der Begründung, dass seineC
aufgebaut ist, bevor seineB
konstruieren kann seineA
) oder Bruch mit Erwartungen (wenn sagte compiler leise, und der mühsam, konstruiertB
vorC
ignorierenE : C, B
, dann dies verstößt gegen das Prinzip der geringsten Verwunderung)), der standard, nur gibt an, dass die abgeleitete Klasse erstellen allevirtual
Basis-Klassen in Ihrer Vererbungshierarchie vor der Erstellung alle nicht-virtual
Basisklassen, das garantiert, dassA
wird immer gültig sein, wennB
undC
konstruiert sind, egal, in welcher Reihenfolge Sie gebaut, die Verhinderung jeglicher UB. (Oder zu verkürzen, die wall of text,virtual
Basisklassen Vorzug gegeben werden, um zu garantieren, dass Sie werden immer gültig sein, wenn die nicht-virtual
Basis-Klassen aufgebaut sind, verhindern, dass UB und/oder halten Sie den compiler aus einem Verstoß gegen die Norm, um zu verhindern, UB.)Den, um die Dinge erscheinen in der Initialisierungs-Liste ist nicht aussagekräftig. In Ihrem Fall, das Basis-Objekt wird immer initialisiert werden zuerst, gefolgt von d1 und d2 in dieser Reihenfolge. Die Initialisierung erfolgt in der Reihenfolge der Ableitung, und um die Mitglieder erscheinen in der definition der Klasse.
Having said that, es ist in der Regel als guter Stil schreiben Sie die Initialisierung Liste in der Reihenfolge der Initialisierung, und einige Compiler wird eine Warnung ausgeben, wenn Sie dies nicht tun.