Jede Klasse sollte einen virtuellen Destruktor haben?

stimmen
45

Java und C # unterstützt die Vorstellung von Klassen , die mit der nicht als Basisklassen verwendet werden finalund sealedKeywords. In C ++ jedoch gibt es keine gute Möglichkeit , eine Klasse zu verhindern , abgeleitet wird , aus den Blättern der Autors Klasse mit einem Dilemma, sollte jede Klasse einen virtuellen Destruktor oder nicht?


Edit: Da C ++ 11 dies nicht mehr der Fall ist, können Sie festlegen , dass eine Klasse ist final.


Auf der einen Seite ein Objekt ein virtuelles destructor geben bedeutet es eine haben wird vtableund somit verbraucht 4 (oder 8 auf 64 - Bit - Maschinen) zusätzliches Bytes pro-Objekt für die vptr.

Auf der anderen Seite, wenn jemand später von dieser Klasse abgeleitet und löscht eine abgeleitete Klasse über einen Zeiger auf die Basisklasse wird das Programm schlecht definiert werden (aufgrund des Fehlen eines virtuellen destructor), und ehrlich gesagt für einen Zeiger zu optimieren pro Objekt lächerlich.

Auf der Greifhand ein virtuelles destructor mit (wohl) bewirbt , dass diese Art gemeint ist polymorph verwendet werden.

Einige Leute denken , dass Sie einen expliziten Grund brauchen nicht einen virtuellen Destruktor zu verwenden (wie es der Subtext dieser Frage ) und andere sagen , dass Sie sie nur verwenden sollten , wenn Sie Grund zu der Annahme haben , dass Ihre Klasse ist von abgeleitet werden, was tun Sie denken?

Veröffentlicht am 09/12/2008 um 19:56
quelle vom benutzer
In anderen Sprachen...                            


8 antworten

stimmen
2

Ich würde „nein“ auf die allgemeine Frage. Nicht jede Klasse braucht man. Wenn Sie , dass die Klasse wissen können , soll nie von vererbt wird, dann gibt es keine Notwendigkeit , die Moll-Overhead zu verursachen. Aber wenn es eine Chance gibt, auf der sicheren Seite und legt eine drin.

Beantwortet am 09/12/2008 um 19:58
quelle vom benutzer

stimmen
8

Nein! Virtuelle Destruktoren werden nur verwendet, wenn ein Objekt einer abgeleiteten Klasse wird über einen Basisklassenzeiger gelöscht. Wenn Ihre Klasse nicht beabsichtigt ist, als Base in diesem Szenario zu dienen, machen Sie nicht den Destruktor virtuell - Sie würden eine falsche Botschaft senden.

Beantwortet am 09/12/2008 um 20:04
quelle vom benutzer

stimmen
53

Jede abstrakte Klasse sollte entweder ein,

  • geschützt destructor, oder,
  • virtueller Destruktor.

Wenn Sie einen öffentlichen nicht-virtuellen Destruktor haben, das ist nicht gut, da es Benutzer erlaubt, durch dieses Zeiger eines abgeleitetes Objekt zu löschen. Da, wie wir alle wissen, ist das Verhalten undefiniert.

Für eine Klasse nicht über einen Zeiger , um es löschen soll, gibt es keinen Grund auch immer einen virtuellen Destruktor zu haben. Es wäre nicht nur Ressourcen verschwenden, aber noch wichtiger wäre es den Nutzern einen falschen Hinweis. Man denke nur an , was beschissen Sinn machen würde , geben , std::iteratoreinen virtuellen Destruktor.

Beantwortet am 09/12/2008 um 20:06
quelle vom benutzer

stimmen
0

Ich werde hinzufügen, dass es Zeiten gab, als ich meinen Kopf auf Destruktoren für eine Weile zerkratzt nicht genannt wurden, wenn ich eine virtuelle in der übergeordneten oder untergeordneten Klasse vergessen. Ich glaube, ich weiß, dass suchen jetzt aber. :)

Jemand könnte argumentieren, dass es Zeiten gibt, die übergeordnete Klasse tut etwas in seinem destructor, dass ein Kind nicht tun soll ... aber das ist wahrscheinlich ein Indikator für etwas falsch mit Ihrer Vererbungsstruktur sowieso.

Beantwortet am 09/12/2008 um 20:14
quelle vom benutzer

stimmen
26

Die Frage ist wirklich, wollen Sie erzwingen Regeln darüber , wie Ihre Klassen verwendet werden sollte? Warum? Wenn eine Klasse keinen virtuellen Destruktor hat, kann jeder die Klasse mit weiß , dass es daraus nicht abgeleitet werden soll, und welche Einschränkungen gelten , wenn Sie es trotzdem versuchen. Ist das nicht gut genug?

Oder benötigen Sie die Compiler einen harten Fehler zu werfen , wenn jemand es wagt , etwas zu tun hatte man nicht erwartet?

Geben Sie die Klasse einen virtuellen Destruktor, wenn Sie für die Menschen daraus zu ziehen beabsichtigen. Sonst nicht, und davon ausgeht, dass jemand Ihren Code intelligent genug ist, den Code richtig zu verwenden.

Beantwortet am 09/12/2008 um 20:18
quelle vom benutzer

stimmen
4

Prüfen Sie diesen Artikel von Herb Sutter :

Leitlinie 4: Eine Basisklasse Destruktor sollte entweder öffentliche und virtuelle oder geschützte und nicht-virtuellen sein.

Beantwortet am 10/12/2008 um 14:08
quelle vom benutzer

stimmen
0

Basisklasse wird abstrakte Klasse, wenn sie mindestens eine rein virtuelle Funktion enthält. Wenn Basis keinen virtuellen Destruktor haben und abgeleitet (abgeleitet von Basis) ist, dann kann man sicher ein abgeleitetes Objekt durch ein abgeleitetes Objekt Zeiger zerstören, aber nicht über einen Basisobjektzeiger.

Beantwortet am 12/05/2010 um 21:04
quelle vom benutzer

stimmen
-3
include<iostream> using namespace std;

class base {
    public: base() {
        cout << "In base class constructor" << endl;
    }

    virtual ~base() {
        cout << "in base class destuctor" << endl;
    }
};

class derived : public base {
    public: derived() {
        cout << "in derived class constructor" << endl;
    }

    ~derived() {
        cout << "in derived class destructor" << endl;
    }
};

int main() {
    base *b; // pointer to the base
    class b = new derived; // creating the derived class object using new
    keyword;
    delete b;
    return 0;
}
Beantwortet am 01/01/2016 um 13:52
quelle vom benutzer

Cookies help us deliver our services. By using our services, you agree to our use of cookies. Learn more