4 Stimmen

Korrekter Weg, um von einer virtuellen Klasse mit nicht-virtuellem Elternteil zu erben

Ich habe diesen Testcode geschrieben, der drei Typen verwendet: struct One ist ein normaler Typ ohne virtuelle Mitglieder, struct Two : One hat eine rein virtuelle Funktion und einen virtuellen Destruktor, und struct Three : Two implementiert Two Schnittstelle.

#include <iostream>

struct One
{
    ~One() {
        std::cout << "~One()\n";
    }
};

struct Two : One
{
    virtual ~Two() {
        std::cout << "~Two()\n";
    }

    virtual void test() = 0;
};

struct Three : Two
{
    virtual ~Three() {
        std::cout << "~Three()\n";
    }

    virtual void test() {
        std::cout << "Three::test()\n";
    }
};

int main()
{
    Two* two = new Three;
    two->test();

    One* one = two;
    delete one;
}

Das ist nicht überraschend, war die Ausgabe dies:

Drei::test()
~One()

Gibt es eine andere Möglichkeit, dies zu beheben, als jeden Destruktor virtuell zu machen? Oder sollten Programmierer einfach vorsichtig sein, um nicht in diese Situation zu geraten? Ich finde es seltsam, dass es keine Warnung beim Kompilieren gibt.

2voto

Bo Persson Punkte 88207

Die einzige "Lösung" besteht darin, die Objekte nicht durch einen Zeiger auf One .

Ob dies ein häufiges Problem ist oder nicht, hängt davon ab, wie Ihre Klassen genutzt werden. Die Standardbibliothek enthält zum Beispiel Strukturen wie unary_function ohne einen virtuellen Destruktor, aber wir sehen kaum, dass er auf diese Weise missbraucht wird.

2voto

Mankarse Punkte 38418

delete one ruft ein undefiniertes Verhalten hervor, weil der dynamische Typ des Objekts nicht mit dem statischen Typ übereinstimmt und der statische Typ keinen virtuellen Destruktor hat.

Der übliche Weg, solche Probleme zu vermeiden, besteht darin, Destruktoren entweder öffentlich und virtuell oder geschützt und nicht-virtuell zu machen (bei Klassen, von denen erwartet wird, dass sie auf diese Weise verwendet werden).

1voto

Gary Punkte 5502

Sie müssen vorsichtig sein und den Destruktor von One virtuell machen. Einige Compiler warnen vor diesem Umstand.

1voto

gumik Punkte 593

Wenn Sie funktionierende Destruktoren in abgeleiteten Klassen wünschen, müssen Sie diese als virtuell definieren. Das ist die einzige Möglichkeit.

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X