Sdílet prostřednictvím


Změny v pořadí inicializace konstruktoru

Pořadí inicializace konstruktorů třídy se změnilo ze spravovaného prostředí jazyka C++ na Visual C++ 2010.

Porovnání pořadí inicializace konstruktoru

V rámci spravovaného prostředí jazyka C++ probíhala inicializace konstruktoru v následujícím pořadí:

  1. Pokud existuje konstruktor základní třídy, pak je vyvolán.

  2. Inicializační seznam třídy je vyhodnocem.

  3. Je proveden kód těla konstruktoru třídy.

Toto pořadí provádění dbá na stejných konvencích jako u nativního programování v jazyce C++. Nový jazyk Visual C++ předepisuje následující pořadí pro provádění CLR (Common Language Runtime) tříd:

  1. Inicializační seznam třídy je vyhodnocem.

  2. Pokud existuje konstruktor základní třídy, pak je vyvolán.

  3. Je proveden kód těla konstruktoru třídy.

Tyto změny platí pouze pro CLR (Common Language Runtime) třídy; pro nativní třídy ve Visual C++ 2010 platí stále předchozí konvence. V obou případech platí pořadí výše zmíněných pravidel skrz celou hierarchii dané třídy.

Zvažte použití kódu v následujícím příkladu pomocí spravovaného rozšíření jazyka C++:

__gc class A
{
public:
   A() : _n(1)
   {
   }

protected:
   int _n;
};

__gc class B : public A
{
public:
   B() : _m(_n)
   {
   }
private:
   int _m;
};

Následující pořadí inicializace konstruktoru, předepsané výše, bychom měli vidět při spuštění, když je konstruovaná nová instance třídy B:

  1. Je vyvolán konstruktor základní třídy A. Člen _n je inicializován na hodnotu 1.

  2. Je vyhodnocen inicializační seznam pro třídu B. Člen _m je inicializován na hodnotu 1.

  3. Je proveden kód těla konstruktoru třídy B.

Nyní zvažte stejný kód s novou syntaxí jazyka Visual C++:

ref class A
{
public:
   A() : _n(1)
   {
   }

protected:
   int _n;
};

ref class B : A
{
public:
   B() : _m(_n)
   {
   }
private:
   int _m;
};

Pořadí provedení při nové instanci třídy B konstruované podle nové syntaxe:

  1. Je vyhodnocen inicializační seznam pro třídu B. Člen _m je inicializován na hodnotu 0 (hodnota 0 je neinicializovaná hodnota třídního člena _m).

  2. Je vyvolán konstruktor základní třídy A. Člen _n je inicializován na hodnotu 1.

  3. Je proveden kód těla konstruktoru třídy B.

Všimněte si, že podobná syntaxe způsobí odlišné výsledky pro tyto příklady kódu. Konstruktor třídy B závisí na hodnotě ze základní třídy A k inicializaci jejího člena. Nicméně konstruktor pro třídu A nebyl dosud vyvolán. Tato závislost může být obzvlášť nebezpečná, když zděděná třída závisí na paměti nebo přidělování zdrojů vyskytujících se v konstruktoru základní třídy.

Co znamená tento přechod ze spravovaného rozšíření jazyka C++ na jazyk Visual C++ 2010

V mnoha případech by měly být změny v pořadí provádění konstruktorů třídy transparentní pro programátora, protože základní třídy nemají ponětí o chování zděděných tříd. Nicméně jak tyto příklady kódu ukazují, tak konstruktory zděděných tříd mohou být výrazně ovlivněny, když jejich inicializační seznamy závisí na hodnotách členů základní třídy. Když přesunete Váš kód ze spravovaného rozšíření jazyka C++ na novou syntaxi, zvažte přesunutí těchto konstrukcí do těla konstruktoru třídy, kde je zaručeno, že dojde k jejich provedení až nakonec.

Viz také

Odkaz

Constructors (C++)

Constructor Initializers

Koncepty

Typy spravovaných (C + +/ CL)