Erben von abstrakter Klasse



  • Hallo,

    ich versuche, von einer abstrakten Klasse zu erben (nennen wir sie A). Die erbende Klasse (=B) soll ebenfalls abstrakt sein.
    A hat bereits einen Konstruktor implementiert. Das will ich für B allerdings nicht. Ich möchte den Konstruktor von A erst von C aufrufen (C erbt von B). Also dann sowas haben wie

    C() : A() {
    // Konstruktor...
    }
    

    Ist das so überhaupt möglich? Wenn ich das machen will, bekomme ich eine Fehlermeldung

    B.h: In constructor ‘B::B()’:
    ../B.h:14: error: no matching function for call to ‘A::A()’
    ../A.h:25: note: candidates are: ...
    

    Scheint so, als kann man das, was ich vor habe nicht machen? Muss man also alle Konstruktoren nacheinander implementieren (also zumindest durchreichen)? Oder geht es doch und ich machen irgend einen Fehler?

    Danke,

    C++Dummy



  • C++Dummy schrieb:

    Ist das so überhaupt möglich? Wenn ich das machen will, bekomme ich eine Fehlermeldung

    Nein, geht nicht.



  • Sobald du einen Konstruktor definierst (Ausnahme der parameterlose Standardkonstuktors) musst du beim
    inititalisieren einer abgeleiteten Klasse den Konstruktor der Basisklasse angeben, sofern die Baisklasse keinen Standardkonstruktor besitzt.



  • Du kannst Basisinitialisierung nur mit direkter Basisklasse machen.
    Bei deiner Hierarchie
    A -> B -> C
    werden beim Anlegen eines C-Objektes von unten weg alle Basisklassen nacheinander initialisiert.
    Erst A, dann B, dann C. Wenn du also an die Stelle der Basisinitialisierung von C kommst hast du bereits ein vollständig initialisiertes B, demnach auch ein vollständig initialisiertes A. Zweimalige Initialisierung einer Basis geht nicht (GCC meldet mir das AFAIK auch genau so).

    // edit:
    Hab das mal kurz ausprobiert, hier der Fehler:

    main.cpp: In constructor »C::C()«:
    main.cpp:17: Fehler: Typ »A« ist keine direkte Basis von »C«
    

    Hier Code:

    struct C : public B
    {
      C() : A(15) // <---
      {}
    };
    

  • Mod

    Die direkte Initialisierung aus der dem Konstruktor der am weitesten abgeleiteten Klasse heraus ist möglich und erforderlich, wenn es sich um eine virtuelle Basisklasse handelt. Ob das in diesem Falle sinnvoll ist, kann ich allerdings nicht beantworten, schließlich wird keine Begründung geliefert, warum diese atypische Initialisierung gewünscht ist.



  • @camper:
    Wie macht man das dann?
    Und warum bei virtuellen Basisklassen? Ich bin bisher immer davon ausgegangen, dass egal wie die Basis aussieht, sie ist immer vor Eintritt in den Konstruktorbody der abgeleiteten Klasse vollständig initialisiert.


  • Mod

    l'abra d'or schrieb:

    @camper:
    Wie macht man das dann?
    Und warum bei virtuellen Basisklassen? Ich bin bisher immer davon ausgegangen, dass egal wie die Basis aussieht, sie ist immer vor Eintritt in den Konstruktorbody der abgeleiteten Klasse vollständig initialisiert.

    Korrekt.

    struct A { A(int) {} };
    struct B : virtual A { B()
      : A(0) // dieser Teil wird nicht ausgeführt, falls B nicht der Typ der am weitesten abgeleiteten Klasse ist. Die Ausdrücke für die Konstruktorparameter von A werden dann nicht ausgewertet
    {} };
    struct C : B { C() : A(1), B() {} };
    int main()
    {
        B b; // A-Subobjekt mit 0 initialisiert
        C c; // A-Subobjekt mit 1 initialisiert
    }
    


  • Ah! Besten Dank.
    Ich hab auch mal nach virtual inheritance gesucht und bin darauf gestoßen:
    http://en.allexperts.com/q/C-1040/virtual-inheritance.htm
    Ich denke ich brauch doch noch den Stroustroup, da sind ja einige Sprachfeatures noch gänzlich unbekannt...
    Wird da auch genau beschrieben, wie man operator new (speziell operator new mit fixer size) implementiert?


Anmelden zum Antworten