Initialisierung von Klassen

Aus RAD Studio
Wechseln zu: Navigation, Suche

Nach oben zu Konstruktoren - Index


Ein Objekt einer Klasse, das nur public-Elemente und keine Konstruktoren oder Basisklassen enthält (dies ist normalerweise eine Struktur), kann mit einer Initialisierer-Liste initialisiert werden. Hat eine Klasse einen Konstruktor, müssen ihre Objekte entweder initialisiert werden oder einen Standardkonstruktor haben. Der Standardkonstruktor wird für Objekte genutzt, die nicht explizit initialisiert werden.

Objekte von Klassen mit Konstruktoren können mit einer Liste von Ausdrücken in Klammern initialisiert werden. Diese Liste wird als Argumentliste für den Konstruktor verwendet. Eine Alternative dazu ist das Gleichheitszeichen (=), gefolgt von einem einzelnen Wert. Dieser Wert kann vom Typ des ersten Arguments sein, das ein Konstruktor dieser Klasse enthält. In diesem Fall gibt es keine weiteren Argumente, oder die restlichen Argumente haben Standardwerte. Als Initialisierungswert kann auch ein Objekt des Klassentyps verwendet werden. Im ersten Fall wird der zugehörige Konstruktor aufgerufen, um das Objekt zu erzeugen. Im zweiten Fall wird zur Initialisierung der Kopierkonstruktor aufgerufen.

class X
{
  int i;
public:
  X();         // function bodies omitted for clarity
  X(int x);
  X(const X&);
};
void main()
{
  X one;        // default constructor invoked
  X two(1);     // constructor X::X(int) is used
  X three = 1;  // calls X::X(int)
  X four = one; // invokes X::X(const X&) for copy
  X five(two);  // calls X::X(const X&)
}

Der Konstruktor kann seinen Elementen auf zweierlei Arten Werte zuweisen:

1. Er kann die Werte als Parameter übernehmen und sie den Elementvariablen im Rumpf der Konstruktorfunktion zuweisen:

class X
{
  int a, b;
public:
  X(int i, int j) { a = i; b = j }
};

2. Er kann aber auch eine Initialisierer-Liste verwenden, die vor dem Funktionsrumpf steht:

class X
{
  int a, b, &c;  // Note the reference variable.
public:
  X(int i, int j) : a(i), b(j), c(a) {}
};

Eine Referenzvariable kann nur in einer Initialisierer-Liste initialisiert werden.

In beiden Fällen weist eine Initialisierung von X x(1, 2) x::a den Wert 1 und x::b den Wert 2 zu. Die zweite Methode - die Initialisierer-Liste - ist ein Mechanismus zur Übergabe von Werten an Basisklassen-Konstruktoren.

Hinweis:  Basisklassen-Konstruktoren müssen als public oder protected deklariert sein, damit sie von einer abgeleiteten Klasse genutzt werden können.

class base1
{
  int x;
public:
  base1(int i) { x = i; }
};
class base2
{
  int x;
public:
  base2(int i) : x(i) {}
};
class top : public base1, public base2
{
  int a, b;
public:
  top(int i, int j) : base1(i*5), base2(j+i), a(i) { b = j;}
};

In dieser Klassenhierarchie würde eine Deklaration von top one(1, 2) die Initialisierung von base1 mit dem Wert 5 und von base2 mit dem Wert 3 ergeben. Die Initialisierungsmethoden lassen sich mischen.

Wie bereits oben erwähnt, werden die Basisklassen in der Reihenfolge ihrer Deklaration initialisiert. Anschließend erfolgt die Initialisierung der Elemente (ebenfalls in der Deklarationsreihenfolge), unabhängig von der Initialisierungsliste.

class X
{
  int a, b;
public:
  X(int i, j) :  a(i), b(a+j) {}
};

In dieser Klasse hat die Deklaration von X x(1,1) eine Zuweisung von 1 an x::a und von 2 an x::b zur Folge.

Basisklassen-Konstruktoren werden vor der Konstruktion der abgeleiteten Klassenelemente aufgerufen. Wenn sich die Werte der abgeleiteten Klasse ändern, hat dies keine Auswirkung auf die Erzeugung der Basisklasse.

class base
{
  int x;
public:
  base(int i) : x(i) {}
};
class derived : base
{
  int a;
public:
  derived(int i) : a(i*10), base(a) { } // Watch out! Base will be
                                        // passed an uninitialized 'a' };

Bei dieser Klassenkonstruktion führt der Aufruf eines derived d(1) nicht zum Wert 10 für das Basisklassen-Element x. Der an den Basisklassen-Konstruktor übergebene Wert ist undefiniert.

Wenn Sie eine Initialisierungsliste in einem Nichtinline-Konstruktor wünschen, platzieren Sie die Liste nicht in die Klassendefinition. Setzen Sie sie stattdessen an einen Punkt, an dem die Funktion definiert ist.

derived::derived(int i) : a(i)
{
  // …
}

Siehe auch