Reiner virtueller Destruktor in C ++

163

Ist es falsch zu schreiben:

class A {
public:
    virtual ~A() = 0;
};

für eine abstrakte Basisklasse?

Zumindest wird das in MSVC kompiliert ... Wird es zur Laufzeit abstürzen?

Ivan Krechetov
quelle
9
Es kann kompiliert werden, aber verknüpft es?
Mooing Duck

Antworten:

218

Ja. Sie müssen auch den Destruktor implementieren:

class A {
public:
    virtual ~A() = 0;
};

inline A::~A() { }

sollte ausreichen.

Und da dies eine negative Abstimmung erhielt, sollte ich klarstellen: Wenn Sie etwas von A ableiten und dann versuchen, es zu löschen oder zu zerstören, wird Ader Destruktor schließlich aufgerufen. Da es rein ist und keine Implementierung hat, kommt es zu undefiniertem Verhalten. Auf einer beliebten Plattform wird der Purecall-Handler aufgerufen und stürzt ab.

Bearbeiten: Korrektur der Konformität der Erklärung, zusammengestellt mit http://www.comeaucomputing.com/tryitout/

MSN
quelle
16
Ähm, ja, das ist es. Rein bedeutet nur, dass eine abgeleitete Klasse auch eine Implementierung bereitstellen muss.
MSN
72
Die Implementierung rein virtueller Funktionen ist in der Tat legal. Sehr nützlich, um eine Standardimplementierung bereitzustellen, aber Unterklassen zu zwingen, sie explizit aufzurufen.
jmucchiello
6
MSN und beachten Sie, wenn Sie diese Definition in der Kopfzeile haben, müssen Sie "inline" davor setzen, um einen Verstoß gegen die ODR (One Definition Rule) zu vermeiden
Johannes Schaub - litb
2
Warum muss A :: ~ A () explizit definiert werden, da ich dachte, dass es für jedes Objekt einen Standarddestruktor gibt? Wie bei jeder Art von Vererbung wird die Destruktorkette immer aufgerufen und der Basisklassen-Destruktor muss nicht immer definiert werden.
JeffD
11
Besser ausgedrückt: Sobald Sie einen Destruktor deklariert haben, wird er nicht automatisch für Sie implementiert.
MSN
49

Private Destruktoren: Sie geben einen Fehler aus, wenn Sie ein Objekt einer abgeleiteten Klasse erstellen - nicht anders. Möglicherweise wird jedoch eine Diagnose angezeigt.

12.4 Destruktoren

6 Ein Destruktor kann als virtuell (10.3) oder rein virtuell (10.4) deklariert werden. Wenn Objekte dieser Klasse oder eine abgeleitete Klasse im Programm erstellt werden, muss der Destruktor definiert werden.

Eine Klasse mit einem reinen virtuellen Destruktor ist eine abstrakte Klasse. Beachten Sie gut:

10.4 Abstrakte Klassen

2 Eine reine virtuelle Funktion muss nur definiert werden, wenn sie mit oder wie mit (12.4) der Syntax der qualifizierten ID (5.1) aufgerufen wird.

[ Anmerkung : Eine Funktionsdeklaration kann nicht sowohl einen reinen Spezifizierer als auch eine Definition enthalten.

Direkt aus dem Entwurf entnommen:

struct C {
   virtual void f() = 0 { }; // ill-formed
};
dirkgently
quelle
14
+1. Ich denke, Herb Sutter hat auch einige gute Informationen dazu: gotw.ca/gotw/031.htm . Es ist interessant festzustellen, dass für jede reine virtuelle Funktion möglicherweise eine Implementierung bereitgestellt wird, nicht nur Destruktoren.
Fred Larson
6
Ja, es ist etwas, was Sie in einem Interview tun, um Ihre Interviewer
auszuflippen
1
Nach meiner Erfahrung ist das eigentlich gar nicht so ungewöhnlich.
@ Neil Butterworth: Welches?
Dirkgently
@Dirk - das Szenario "jede Funktion". Es ist nicht ungewöhnlich, dass es verwendet wird, um ein allgemeines Verhalten zu implementieren.