Abstrakte Destruktoren



  • Vielleicht wäre es hilfreich wenn du versuchst dieses Experiment noch einmal unvoreingenommen zu interpretieren.



  • finix schrieb:

    Vielleicht wäre es hilfreich wenn du versuchst dieses Experiment noch einmal unvoreingenommen zu interpretieren.

    😕

    Gruß,

    Simon2.



  • Simon2 schrieb:

    Ergo => Der Compiler handhabt pure-virt-Dtors anders als "normale pure-virt-funcs" .... so, wie ich vermutet habe. Bei dem Einen duldet (ja sogar: fordert implizit) er etwas, was er beim Anderen verbietet.

    Nein, nicht wirklich. Der einzige Unterschied ist dass jede Klasse (logischerweise) einen Destructor benötigt und der Compiler (praktischerweise) ggf. implizit einen Destructor generiert, ob (pure) virtual oder nicht.

    Unabhängig davon ist der Gedanke den Destructor überschreiben zu müssen ohnehin recht unsinnig, denn das ist, ähnlich wie beim Constructor, schlicht nicht möglich.



  • Hi,

    ich habe das Gefühl, dass wir uns immer weniger verstehen, je länger wir uns unterhalten.

    Der von mir genannte Unterschied im Handling der Implementation von "pure-virt-DTors" und "pure-virt-funcs" ist (auch auf die Gefahr, mich zu wiederholen):
    - die einen werden benötigt (Dtors),
    - die anderen werden verboten (Funcs)

    finix schrieb:

    ...der Compiler (praktischerweise) ggf. implizit einen Destructor generiert, ob (pure) virtual oder nicht...

    Also MEIN Compiler (gcc 3.4.4) generiert bei der Angabe von "= 0" KEINEN Dtor, sondern läuft auf einen entsprechenden Linkerfehler.

    finix schrieb:

    ...
    Unabhängig davon ist der Gedanke den Destructor überschreiben zu müssen ohnehin recht unsinnig, denn das ist, ähnlich wie beim Constructor, schlicht nicht möglich.

    Was meinst Du mit "Überschreiben" ?
    Normale Polymorphie mit Destruktoren ist nicht nur erlaubt, sondern geboten .... mit Konstruktoren dagegen wirklich nicht möglich (bzw. nur über Spezialtechniken).
    Wahrscheinlich meinst Du etwas Anderes mit dieser Aussage.

    Gruß,

    Simon2.



  • Simon2 schrieb:

    Also MEIN Compiler (gcc 3.4.4) generiert bei der Angabe von "= 0" KEINEN Dtor, sondern läuft auf einen entsprechenden Linkerfehler.

    Zum Mitschreiben: 😉
    1. jede Klasse hat einen dtor
    2. deklarierst Du ihn nicht explizit, generiert der Compiler einen
    3. deklarierst Du ihn explizit, musst Du ihn auch definieren, sonst ➡ Linkerfehler
    4. deklarierst Du einen pure virtual dtor, ist 2. nicht erfüllt. Daraus folgt 3.



  • LordJaxom schrieb:

    ...
    Zum Mitschreiben: 😉
    1. jede Klasse hat einen dtor
    2. deklarierst Du ihn nicht explizit, generiert der Compiler einen
    3. deklarierst Du ihn explizit, musst Du ihn auch definieren, sonst ➡ Linkerfehler
    4. deklarierst Du einen pure virtual dtor, ist 2. nicht erfüllt. Daraus folgt 3.

    So hatte ich das ja auch verstanden, sah aber einen Widerspruch zu finix' Aussage "Der Compiler generiert ggf. implizit einen Destructor ..., ob (pure) virtual oder nicht.."

    Offensichtlich tut er es bei "=0" (und das ist der Fall, den wir hier seit dem ersetn Posting betrachten) eben NICHT.
    Natürlich kann sich das "ggf." auf etwas anderes als auf "implizit" beziehen, aber dann verstehe ich den Satz nicht besser.

    Sorry, wenn das Alles jetzt recht kleinlich wirkt, aber ich habe (offensichtlich) immer noch nicht begriffen, wo mein Verständnis des Ganzen falsch ist. Aber es muß ja falsch sein, weil sonst finix sich nicht die Mühe machte, mir das immer wieder zu bescheinigen. 😞
    Und ich würd's halt einfach gerne verstehen ....

    EDIT - Eine kleine Anmerkung (nur "comilerverifiziert") zu Deiner Liste habe ich nun aber doch: Sie hat nur deswegen einen Sinn, weil DToren eigentlich immer gebraucht werden (solange man überhaupt ein Objekt erzeugt - und sei es implizit). Normale Memberfunktionen müssen nicht implementiert sein - weil man auf ihre Benutzung verzichten kann.

    Gruß,

    Simon2.



  • Ich frage mich, wer immer diesen Unsinn in die Welt setzt, dass "pure virtual = keine Implementation" bedeutet? Diese Mißverständnis scheint mir auch das Problem in diesem Thread zu sein.

    Wenn man pure virtual unbedingt an Implementationen fest machen will (nicht wirklich sinnvoll), dann sollte man sich vorstellen, dass pure virtual bedeutet "Implementation wird nicht in die vtable-Eingetragen", d.h. eine pure virtual function kann nicht über dynamische Bindung aufgerufen werden. Sie muss immer explizit aufgerufen werden.

    Genau so ein expliziter Aufruf passiert übrigens auch im Dtor (und ist der Grund, warum ein pure virtual Dtor eine Implementation haben *muss*). Die Implementation eines Dtors wird durch den Compiler automatisch um Aufrufe von Basisklassendtoren ergänzt. Egal ob der Dtor explizit oder implizit definiert wurde.

    So hatte ich das ja auch verstanden, sah aber einen Widerspruch zu finix' Aussage "Der Compiler generiert ggf. implizit einen Destructor ..., ob (pure) virtual oder nicht.."

    Das bezog sich garantiert auf *abgeleitete* Klassen. Die (pure) virtualität eines Basisklassendtors hat *keinen* Einfluss auf die Generierung von Destruktoren in abgeleiteten Klassen.

    Offensichtlich tut er es bei "=0" (und das ist der Fall, den wir hier seit dem ersetn Posting betrachten) eben NICHT.
    Natürlich kann sich das "ggf." auf etwas anderes als auf "implizit" beziehen, aber dann verstehe ich den Satz nicht besser.

    Natürlich nicht für die Klasse, in der der Dtor *deklariert* wurde. Die (pure) virtualität ist in diesem Punkt völlig irrelevant. Die *Deklaration* eines "Special-Members" verhindert *immer* eine implizite Definition.



  • Simon2 schrieb:

    Der von mir genannte Unterschied im Handling der Implementation von "pure-virt-DTors" und "pure-virt-funcs" ist (auch auf die Gefahr, mich zu wiederholen):
    - die einen werden benötigt (Dtors),
    - die anderen werden verboten (Funcs)
    [...]
    So hatte ich das ja auch verstanden, sah aber einen Widerspruch zu finix' Aussage "Der Compiler generiert ggf. implizit einen Destructor ..., ob (pure) virtual oder nicht.."

    Der Einwurf "ob (pure) virtual oder nicht" bezog sich in der Tat auf die abgeleitete Klasse, ich dachte das wäre aus dem Kontext heraus noch klar.

    Und wie HumeSikkins auch schon erwähnt hat ist die Implementation auch bei normalen Methoden keineswegs verboten. Das ist auch durchaus sinnvoll, z.B. wenn es eine Defaultimplementation (logisch gesehen) gibt, diese, aus welchen Gründen auch immer, aber vom Ableitenden bewusst aufgerufen werden soll, oder wenn z.B. für eine Operation zum Teil die Basisklasse zuständig ist, zum Teil die Abgeleitete.

    Simon2 schrieb:

    finix schrieb:

    ...
    Unabhängig davon ist der Gedanke den Destructor überschreiben zu müssen ohnehin recht unsinnig, denn das ist, ähnlich wie beim Constructor, schlicht nicht möglich.

    Was meinst Du mit "Überschreiben" ?
    Normale Polymorphie mit Destruktoren ist nicht nur erlaubt, sondern geboten .... mit Konstruktoren dagegen wirklich nicht möglich (bzw. nur über Spezialtechniken).
    Wahrscheinlich meinst Du etwas Anderes mit dieser Aussage.

    Nein, ich meinte was ich schrieb: Destruktoren werden genau wie Konstruktoren weder geerbt noch können sie überschrieben werden, siehe auch Humes Post dazu.



  • finix schrieb:

    ...Der Einwurf "ob (pure) virtual oder nicht" bezog sich in der Tat auf die abgeleitete Klasse, ich dachte das wäre aus dem Kontext heraus noch klar....

    Sorry, war mir nicht klar. Aber jetzt.

    finix schrieb:

    ...Und wie HumeSikkins auch schon erwähnt hat ist die Implementation auch bei normalen Methoden keineswegs verboten. ...

    Bis eben dachte ich noch: Sieht mein Compiler aber anders.
    Aber ein erneuter Test (und Finden im Standard) hat ergeben, dass Ihr Recht habt und ich Unrecht.

    Simon2 schrieb:

    finix schrieb:

    ...
    Unabhängig davon ist der Gedanke den Destructor überschreiben zu müssen ohnehin recht unsinnig, denn das ist, ähnlich wie beim Constructor, schlicht nicht möglich.

    Was meinst Du mit "Überschreiben" ? ...

    Nein, ich meinte was ich schrieb: Destruktoren werden genau wie Konstruktoren weder geerbt noch können sie überschrieben werden, siehe auch Humes Post dazu.[/quote]
    Nochmal: was meinst Du mit "überschreiben" ? Meinst Du damit "in der vtable mit selbem Namen ersetzen" ?

    Ich kenne das nur aus

    class A {
    public:
        virtual ~A() { }
    };
    
    class B: public A {
        virtual ~B() { }
    };
    
    A* a = new B;
    delete a; // ruft ~B() auf, der dann implizit ~A() aufruft
    

    Meinst Du das ? Und was ist dann "nicht erlaubt" ? In B einen ~A() zu definieren ?

    BTW: Danke für Eure Beharrlichkeit ! Einen Irrtum von mir habt Ihr schon aufgeklärt. 👍

    Gruß,

    Simon2.



  • Simon2 schrieb:

    Nochmal: was meinst Du mit "überschreiben" ? Meinst Du damit "in der vtable mit selbem Namen ersetzen" ?

    Ich kenne das nur aus

    class A {
    public:
        virtual ~A() { }
    };
    
    class B: public A {
        virtual ~B() { }
    };
    
    A* a = new B;
    delete a; // ruft ~B() auf, der dann implizit ~A() aufruft
    

    Meinst Du das ? Und was ist dann "nicht erlaubt" ? In B einen ~A() zu definieren ?

    Im Prinzip ja. Du kannst per virtual dafür sorgen dass der Konstruktor von B aufgerufen wird, aber nicht verhindern dass ~A aufgerufen wird. Und ~A existiert in B ganz einfach nicht.


Anmelden zum Antworten