Fragezu: virtuelle/abstrakte Methoden, Ableiten etc.



  • also eigentlich handelt es sich hier nicht um ein konretes problem sondern um eine verständnisfrage.

    gut, nun zur frage:
    ich habe eine abstrakte Basisklasse, welche die Funktion
    virtual void ShutdownSystem() = 0 ;
    deklariert (ich hoffe das ist die richtige bezeichnung dafür)
    ich leite nun z. B. meinen Server davon ab und implemetiere nun diese Funktion.
    Allgemein wird public vererbt und es handelt sich um eine einfache Vererbung, sprich keine virtelle Vererbung.
    Destruktoren sind in Basis und abgeleiteter Klasse ebenfalls virtuell.

    Nun zur Frage, wenn ich ShutdownSystem im Destruktor der Basisklasse rufe was passiert dann?

    a) die Implementierung der abgeleiteten Klasse wird gerufen
    b) es fliegt mir die Methode mit ner pure function call Exception um die ohren



  • Jason_Frost schrieb:

    ... deklariert (ich hoffe das ist die richtige bezeichnung dafür)

    Ja.

    Jason_Frost schrieb:

    Allgemein wird public vererbt und es handelt sich um eine einfache Vererbung, sprich keine virtelle Vererbung.

    Multiple Inheritance != Virtual Inheritance ⚠

    Jason_Frost schrieb:

    Nun zur Frage, wenn ich ShutdownSystem im Destruktor der Basisklasse rufe was passiert dann?

    a) die Implementierung der abgeleiteten Klasse wird gerufen
    b) es fliegt mir die Methode mit ner pure function call Exception um die ohren

    Was hat denn dein Test ergeben? A, b oder vielleicht c?



  • Im Destructor der Basisklasse hast du nurmehr die virtuellen Funktionen der Basisklasse zur Verfügung. Laut Standard hat es sich dort dann also um die Ohren zu fliegen wie du das sagst 😉
    Was passiert wenn du die Funktion in der Basisklasse pure machst aber trotzdem implementierst (ja, das geht!) weiss ich nicht - müsste ich nachgucken bzw. ausprobieren.



  • es darf keine funktion einer abgeleiteten klasse aufgerufen werden, da der dtor der abgeleiteten klasse schon abgearbeitet wurde und es kein abgeleitetes objekt mehr gibt (und zufällig hat der dtor der abgeleiteten klasse als mit unsichtbarem befehl den vptr auf die vtable der basisklasse umgebogen, so wie der ctor seinerzeit ihn auf die vtable der abgeleiteten klasse umgebogen hat).
    ein pure-virtual-function-call ist viel leichter zu jagen, als ein zugriff auf den {gelöschten!} string, der member der geerbten klasse ist und praktisch immer funktioniert (hatte mal ein projekt, wo es ca. 200000 zu 1 funktionierte und im gegenzug nur alle zwei wochen unvorhersagbar ausstieg), außer manchmal, wenn genau die paar freigegebenen bytes nen 64-k-block ganz freigemacht haben (mit pech: *und* zwischen dtor der geerbten klasse und dtor der basisklasse ein prozesswechsel war (mit noch mehr pech: *und* das bs oder das laufzeitsystem lust hatte, den speicher freizugeben)).
    gegen eine implemetierte pure virtual function der basisklasse ist gar nix einzuwenden.
    eigentlich doof vom compiler, wenn er erlaubt, im dtor ne nicht-implementierte pure-virtual-function aufzurufen. wäre mal sinnvoller, als wegen "void main()" rumzuwarnen. ups, der compiler weiß ja gar nicht, ob sie in einer anderen übersetzungseinheit implementiert wurde.



  • dachte ich mir, in gewisser weise auch logisch dass fall b eintritt. hab mir da vorgestern mit sowas ins knie geschossen und nachdem ich das nachvollzogen hat warum und wieso, dacht ich mal hab ichs tatsächlich richtig verstanden. postest es hier einfach mal.

    das interessante ist, wenn man die Methode in einer andere nicht virtuellen Methode unterbringt und diese ruft sagt der Compiler nichts.
    Wenn man es direkt in dtor ruft, dann gibts nenn linkerfehler und wenn ich virtual vererbe kann ichs im dtor ebenfalls reinschreiben und es kracht dann eben.
    was sich wohl bei virtueller vererbung durch das mögliche vorhandensein mehrfacher vtable

    @finix
    Multiple Inheritance != Virtual Inheritance
    das weiss ich ;), habs wohl zu undeutlich geschrieben



  • Der Grund dafür liegt in der speziellen Verarbeitung der Destruktoren - die bauen dein Objekt stückweise von außen nach innen ab. Das heißt, in dem Moment, wo der Destruktor der Basisklasse aufgerufen wird, ist der Dtor der abgeleiteten Klasse schon fertig und hat die Teile des Objekts, die zur abgeleiteten Klasse gehören, schon entsorgt (inklusive der vtable - so daß du nur noch die abstrakte Methode hast).

    Im Gegensatz dazu arbeiten "normale" Methoden mit einem vollständig aufgebauten Objekt, haben also auch immer die korrekte vtable, um die spezialisierte Version deiner Methode zu erreichen.

    (PS: Im Konstruktor dürftest du die selben Probleme mit der abstrakten Methode bekommen, da der Anteil der abgeleiteten Klasse (inklusive deiner Spzialisierung) noch nicht angelegt ist)


Anmelden zum Antworten