Initialisierungsliste vs. Konstruktor Body



  • Hallo,

    ich wollte mal nachfragen, was der Vorteil ist eine Initialisierungsliste für die Initialisierungen der Klasse anstatt, anstatt dies ganz normal im Konstruktor "Body" zu machen?
    Kann man auch Variablen die mittels anderer Methoden initialisiert werden müssen in der Initialisierungsliste initialisieren?
    Macht es überhaupt Sinn in einer Klasse deren Konstruktur Body man man für bestimmte Zwecke braucht überhaupt Variablen mit der Initialisierungsliste zu initialisieren? Ich meine, dann wird ja sowieso der Konstruktor aufgerufen?

    Danke euch!

    Viele Grüße
    Manfred



  • Mannid schrieb:

    ich wollte mal nachfragen, was der Vorteil ist eine Initialisierungsliste für die Initialisierungen der Klasse anstatt, anstatt dies ganz normal im Konstruktor "Body" zu machen?

    1. Findet eine "Initialisierung" nur in der Initialisierungsliste statt (im Konstruktorrumpf sind Variablen bereits initialisiert, und das was man dort macht sind dann Zuweisungen).
    2. Referenzen und Konstanten können ausschließlich initialisiert werden (sprich nur in der Initialisierungsliste gesetzt werden).

    Mannid schrieb:

    Kann man auch Variablen die mittels anderer Methoden initialisiert werden müssen in der Initialisierungsliste initialisieren?

    Ja.

    Mannid schrieb:

    Macht es überhaupt Sinn in einer Klasse deren Konstruktur Body man man für bestimmte Zwecke braucht überhaupt Variablen mit der Initialisierungsliste zu initialisieren? Ich meine, dann wird ja sowieso der Konstruktor aufgerufen?

    Grundsätzlich ist eine initialisierung mittels Initialisierungsliste immer vorzuziehen. Einzig zu beachten ist dabei, das die initialisierung in der Reihenfolge abläuft, in der die Membervariablen im Header deklariert sind, und nicht in der Reihenfolge wie man sie in der Initialisierungsliste schreibt (Wichtig für Initialisierungen die voneinander abhängig sind). Daher sind bei mir Initialisierungslisten in der gleichen Reihenfolge wie im Header gehalten.



  • Kleines Beispiel:

    class A
    {
        private:
            const int a; // \ Zuweisung von Konstanten und Referenzen ist nur in der
            int & b;     // / Initialisierungsliste, nicht im Konstruktorrumpf zulässig.
            int c;
            int d;
    
        public:
            A(int & refB)
            :   a(10),    // Unabhängig davon, welche Reihenfolge man in der
                b(refB),  // Initialisierungsliste verwendet, findet die
                c(foo()), // Initialisierung in Reihenfolge der Deklaration statt.
                d(c + 10) // Wichtig für abhängige Initialisierungen wie z.B. bei d
            {
                c = 20;   // Dies ist eine Zuweisung, KEINE Initialisierung
            }
    
            static int foo()
            {
                return 10;
            }
    };
    

    Das im Konstruktorrumpf eine Zuweisung erfolgt, statt einer Initialisierung hat noch andere Konsequenzen, gerade bei komplexen Objekten.

    // Nehmen wir mal folgendes an: Klasse B ist eine Klasse mit einem Komplexen
    // Konstruktor / Zuweisungsoperator.
    
    class B { /**/ };
    
    // Ersten Ansatz, der wohl deinen bisherigen Verständnis entspricht:
    class A1
    {
        private:
            B b;
        public:
            A1()
            // <-- Hier erfolgt der Aufruf des Standardkonstruktors von b
            {
                b = B(123); // <-- Hier im schlechtesten Fall neben einen
                            //     weiteren Konstruktoraufruf noch eine Zuweisung
            }
    };
    
    // Zweiter Ansatz über Initialisierungsliste:
    class A1
    {
        private:
            B b;
        public:
            A1()
            :   b(123) // <-- Hier erfolgt der entsprechende Konstruktoraufruf
            {
            }
    };
    

    Falls man keine Initialisierungsliste macht, laufen also mehrere Aktionen ab, und zudem ist ein Standardkonstruktor erforderlich.

    Weitere Anwendung der Initialisierungsliste:
    Mittels der Initialisierungsliste lässt sich von der Basisklasse ein anderer als der Standardkonstruktor verwenden.

    class Base
    {
        public:
            Base();
            Base(int i);
    };
    
    class Derivered : Base
    {
        public:
            Derivered()
            // <-- Ohne explizite Angabe, Aufruf von Base()
            {
            } 
    
            Derivered(int a, int b)
            :   Base(a) // Explizite Verwendung von Base(int)
            {
            }
    };
    

Anmelden zum Antworten