[gelöst] virtuelle Funktion aus Konstruktor der abgeleiteten Klasse aufrufen. Sicher?



  • Hallo,

    wie jeder weiß, darf man in Basisklassenkonstruktoren keine virtuellen Funktionen aufrufen. Aber wie sieht das in Konstruktoren der abgeleiteten Klasse aus, wenn diese "final" ist (laut meinem Entwurf, was ich aber in C++ nicht enforcen kann)?

    Beispiel:

    class Base {
        virtual void foo() = 0;
    };
    
    class Derived: public Base {
        Derived() { foo(); }
        void foo() { printf("Hello"); }
    };
    

    Kann ich davon ausgehen, dass der Konstruktor von Derived das "richtige" foo, also Derived::foo, aufruft?

    Gruß,
    Phil





  • Beim Eintritt in den Konstruktor-Rumpf ist dein Objekt fertig initialisiert - es ist ein Derived. Somit sollte auch das richtige foo() aufgeufen werden.
    Sonst könntest du ja auch keine nicht-virtuellen Member von Derived im Konstruktor aufrufen.

    Nur wenn du jetzt von Derived nochmal ableitest (weil du später mal nichtmehr dran denkst dass foo virtual ist und inm Konstruktor von Derived aufgerufen wird) bekommst du das übliche nicht gewollte Verhalten, dass in Derived2() plötzlich Derived::foo() ausgeführt wird.



  • Okay, also genau wie ich gedacht habe.
    Mir fehlt das "final" Keyword in C++. Muss ich wohl SEHR gut dokumentieren.


  • Administrator

    PhilippM schrieb:

    Okay, also genau wie ich gedacht habe.
    Mir fehlt das "final" Keyword in C++. Muss ich wohl SEHR gut dokumentieren.

    Tipp:

    class Base { 
        virtual void foo() = 0; 
    }; 
    
    class Derived: public Base { 
        Derived() { doFoo(); } 
        void doFoo() { std::cout << "Hello"; }
        virtual void foo() { doFoo(); } 
    };
    

    Schon brauchst du kein final mehr und man kann gefahrlos davon ableiten.

    Wozu final bei Klassen überhaupt verwenden? Habe bisher kaum einen sinnvollen Einsatz gesehen ... um ehrlich zu sein nicht mal einen einzigen.

    Grüssli



  • http://msdn.microsoft.com/de-de/library/ms173150(VS.80).aspx schrieb:

    Eine versiegelte Klasse kann nicht als Basisklasse verwendet werden. Aus diesem Grund kann sie auch keine abstrakte Klasse sein. Versiegelte Klassen werden hauptsächlich verwendet, um Ableitungen zu verhindern. Weil sie nicht als Basisklasse verwendet werden können, können Aufrufe an versiegelte Klassenmember durch Laufzeitoptimierungen etwas beschleunigt werden.

    Findet man bei .NET und Java.


  • Administrator

    Zeus schrieb:

    http://msdn.microsoft.com/de-de/library/ms173150(VS.80).aspx schrieb:

    Eine versiegelte Klasse kann nicht als Basisklasse verwendet werden. Aus diesem Grund kann sie auch keine abstrakte Klasse sein. Versiegelte Klassen werden hauptsächlich verwendet, um Ableitungen zu verhindern. Weil sie nicht als Basisklasse verwendet werden können, können Aufrufe an versiegelte Klassenmember durch Laufzeitoptimierungen etwas beschleunigt werden.

    Findet man bei .NET und Java.

    Ich weiss schon was final oder sealed tun, nur ob es sinnvolle Einsatzgebiete gibt, wage ich sehr stark zu bezweifeln. Im allgemeinen liest man nur überall immer wieder:
    "Aus unerklärlichen Gründen wurde die Klasse als final/sealed deklariert, wodurch dies und das nun nicht möglich ist und ein grosser Umweg gemacht werden muss."

    Das Problem liegt darin, dass der Entwickler gar nicht sinnvoll beurteilen kann, ob von seiner Klasse abgeleitet werden wird oder nicht.

    Dass .Net dann von einem leichten Performancegewinn spricht, macht die Sache nicht gerade besser, sondern macht sie eher lächerlich. Einen leichten Performancegewinn wird in .Net wohl kaum ins Gewicht fallen. Dafür verhindert man die Erweiterbarkeit der Klasse. Wie gesagt, ich habe noch nie einen sinnvollen Einsatz gesehen. Falls mir den jemand aufzeigen könnte, wäre ich dankbar.

    Grüssli


Log in to reply