Reihenfolge der Konstruktoraufrufe

Sehen wir uns folgendes Programm an:

    #include <iostream>
    using namespace std;

    class Global
    {
    public:
      Global() { cout<<"Global Ctor\n"; }
      ~Global() { cout<<"Global Dtor\n"; }
    };

    class virtual_base
    {
    public:
      virtual_base() { cout<<"virtual_base Ctor\n"; }
      virtual ~virtual_base() { cout<<"virtual_base Dtor\n"; }
    };

    class normal_base1 : virtual public virtual_base
    {
    public:
      normal_base1() { cout<<"normal_base1 Ctor\n"; }
      virtual ~normal_base1() { cout<<"normal_base1 Dtor\n"; }
    };

    class normal_base2 : virtual public virtual_base
    {
    public:
      normal_base2() { cout<<"normal_base2 Ctor\n"; }
      virtual ~normal_base2() { cout<<"normal_base2 Dtor\n"; }
    };

    class normal1
    {
    public:
      normal1() { cout<<"normal1 Ctor\n"; }
      ~normal1() { cout<<"normal1 Dtor\n"; }
    };

    class normal2
    {
    public:
      normal2() { cout<<"normal2 Ctor\n"; }
      ~normal2() { cout<<"normal2 Dtor\n"; }
    };

    class Local : public normal_base1, public normal_base2
    {
    private:
      normal2 n;
      normal1 m;
    public:
      Local() { cout<<"local Ctor\n"; }
      ~Local() { cout<<"local Dtor\n"; }
    };

    Global global;

    int main()
    {
      Local local;
    }
    

Die Ausgabe dazu sieht so aus:

Global Ctor
virtual_base Ctor
normal_base1 Ctor
normal_base2 Ctor
normal2 Ctor
normal1 Ctor
local Ctor
local Dtor
normal1 Dtor
normal2 Dtor
normal_base2 Dtor
normal_base1 Dtor
virtual_base Dtor

Die Reihenfolge sieht also so aus:

  1. globale Objekte (Reihenfolge untereinander undefiniert)
  2. virtuelle Basisklassen in Erscheinungsreihenfolge
  3. Basisklassen in Erscheinungsreihenfolge
  4. Membervariablen der eigenen Klasse in Deklarationsreihenfolge
  5. eigener Konstruktor

Die Destruktorenaufrufe finden natürlich in umgekehrter Reihenfolge statt.

top