3 Stimmen

Spielt die Reihenfolge der Initialisierer von Basisklassen und Member-Variablen eine Rolle?

Ist die Reihenfolge der Initialisierer für den Konstruktor einer Klasse wichtig?

Angenommen, ich habe:

Klasse MyClass : BaseClass
{
      int a, b, c;

   public:
      MyClass(int);
}

z.B. 1:

MyClass::MyClass(int fürBase) :
  a(7),
  b(14),
  c(28),
  BaseClass(fürBase) { }

z.B. 2:

MyClass::MyClass(int fürBase) :
  BaseClass(fürBase),
  a(7),
  b(14),
  c(28) { }

Würde Beispiel 1 etwas anderes als Beispiel 2 tun?

10voto

Lightness Races in Orbit Punkte 367630

Würde Beispiel 1 etwas anderes als Beispiel 2 tun?

Nein. Die Initialisierungsreihenfolge wird vom Standard vorgegeben und nicht von der Reihenfolge, in der Sie die Initialisierer schreiben:

[C++11: 12.6.2/10]: Bei einem nicht-delegierenden Konstruktor erfolgt die Initialisierung in folgender Reihenfolge:

  • Zuerst, und nur für den Konstruktor der am stärksten abgeleiteten Klasse (1.8), werden virtuelle Basisklassen in der Reihenfolge initialisiert, in der sie bei einer Depth-First-Left-to-Right-Traversal des gerichteten azyklischen Graphen der Basisklassen erscheinen, wobei "von links nach rechts" die Reihenfolge des Erscheinens der Basisklassen in der Basisklassen-Spezifikationsliste der abgeleiteten Klasse ist.
  • Dann werden direkte Basisklassen in der Deklarationsreihenfolge initialisiert, wie sie in der Basisklassen-Spezifikationsliste 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 (erneut unabhängig von der Reihenfolge der Mem-Initialisierer).
  • Zuletzt wird der Anweisungsblock des Konstruktor-Rumpfes ausgeführt.

Tatsächlich erhalten Sie möglicherweise eine Warnung, wenn Sie sie in einer anderen Reihenfolge schreiben und eine von der anderen abhängt, dann erhalten Sie möglicherweise eine Warnung:

struct T {
   std::vector v;
   int w;

   T(int w) : w(w), v(0, w) {}
};

int main() {
   T t(3);
}

// g++ 4.1.2:
// t.cpp: In constructor 'T::T(int)':
// Line 3: warning: 'T::w' will be initialized after
// Line 2: warning:   '__gnu_debug_def::vector > T::v'
// Line 5: warning:   when initialized here

5voto

celtschk Punkte 18621

Die Reihenfolge spielt für den Compiler keine Rolle (die Initialisierungsreihenfolge ist immer zuerst Basisklassen und immer Basisklassen in der Ableitungsreihenfolge und Member in der Deklarationsreihenfolge), aber für den Leser spielt sie eine Rolle: Es ist sehr verwirrend, wenn die Reihenfolge, in der Sie die Initialisierer angeben, nicht mit der Reihenfolge übereinstimmt, in der sie ausgeführt werden. Während es in den meisten Fällen keine Rolle spielt, können in einigen Fällen subtile Fehler auftreten, z.B.

struct Derived: Base
{
  int member;
  Derived();
}

Derived::Derived():
  member(3),
  Base(member) // Dies wird *vor* der Initialisierung von member ausgeführt!
{
}

Dieser Fehler würde deutlicher werden, wenn die Initialisierer in der richtigen Reihenfolge angegeben würden:

Derived::Derived():
  Base(member), // Jetzt sehen wir sofort, dass member nicht initialisiert ist
  member(3),
{
}

4voto

UncleBens Punkte 39755

Es spielt keine Rolle, in welcher Reihenfolge Sie die Initialisierer in der Konstruktor-Initialisierungsliste auflisten. Elemente werden in der Reihenfolge initialisiert, in der sie deklariert sind, und Basen werden vor Elementen initialisiert.

Es kann jedoch problematisch sein, Initialisierer in einer anderen Reihenfolge aufzulisten, wenn der Anfangswert eines Teilobjekts von den Werten anderer Teilobjekte abhängt.

class A
{
  int y, x;
  A(int x_value): x(x_value), y(x) {}
};

Da y vor x initialisiert wird, erhält es einen Müllwert, und die Reihenfolge der Initialisierungsliste verbirgt den Fehler nur. Deshalb verdient dies eine Compilerwarnung.

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X