Czysty wirtualny destruktor w C ++

163

Czy źle jest pisać:

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

dla abstrakcyjnej klasy bazowej?

Przynajmniej to kompiluje się w MSVC ... Czy ulegnie awarii w czasie wykonywania?

Ivan Krechetov
źródło
9
Może się kompilować, ale czy łączy?
Mooing Duck,

Odpowiedzi:

218

Tak. Musisz także zaimplementować destruktor:

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

inline A::~A() { }

powinno wystarczyć.

A ponieważ głosowanie negatywne zostało odrzucone, powinienem wyjaśnić: jeśli uzyskasz cokolwiek z A, a następnie spróbujesz to usunąć lub zniszczyć, w Akońcu zostanie wywołany destruktor. Ponieważ jest czysty i nie ma implementacji, nastąpi niezdefiniowane zachowanie. Na jednej popularnej platformie spowoduje to wywołanie obsługi purecall i awarię.

Edycja: ustalenie deklaracji, aby była bardziej zgodna, skompilowane z http://www.comeaucomputing.com/tryitout/

MSN
źródło
16
Tak jest. Czysty oznacza tylko, że klasa pochodna również musi zapewnić implementację.
MSN
72
Wdrażanie czystych funkcji wirtualnych jest w rzeczywistości legalne. Bardzo przydatne do dostarczania domyślnej implementacji, ale zmuszając podklasy do jawnego wywoływania jej.
jmucchiello,
6
MSN i zwróć uwagę, że jeśli masz tę definicję w nagłówku, musisz wstawić przed nią „inline”, aby uniknąć naruszenia ODR (zasada jednej definicji)
Johannes Schaub - litb
2
Dlaczego A :: ~ A () musi być jawnie zdefiniowane, skoro, jak sądziłem, istnieje domyślny destruktor dla każdego obiektu? Jak w przypadku każdego rodzaju dziedziczenia, łańcuch destruktorów jest zawsze wywoływany, a destruktor klasy bazowej nie musi być zawsze definiowany.
jeffD
11
Lepszym sposobem wyrażenia tego jest to, że po zadeklarowaniu destruktora nie jest on automatycznie zaimplementowany.
MSN
49

Prywatne destruktory: dadzą ci błąd podczas tworzenia obiektu klasy pochodnej - nie inaczej. Może się jednak pojawić diagnostyka.

12.4 Destruktory

6 Destruktor można zadeklarować jako wirtualny (10.3) lub czysty wirtualny (10.4); jeśli w programie zostaną utworzone obiekty tej klasy lub klasy pochodnej, należy zdefiniować destruktor.

Klasa z czystym wirtualnym destruktorem jest klasą abstrakcyjną. Zwróć uwagę:

10.4 Klasy abstrakcyjne

2 Czysta funkcja wirtualna musi być zdefiniowana tylko wtedy, gdy jest wywoływana z lub tak jakby z (12.4) składnią Qualified-ID (5.1).

[ Uwaga : deklaracja funkcji nie może zawierać zarówno czystego specyfikatora, jak i definicji - uwaga końcowa]

Wzięte prosto z wersji roboczej:

struct C {
   virtual void f() = 0 { }; // ill-formed
};
dirkgently
źródło
14
+1. Myślę, że Herb Sutter również ma dobre informacje na ten temat: gotw.ca/gotw/031.htm . Warto zauważyć, że każda czysta funkcja wirtualna może mieć zapewnioną implementację, a nie tylko destruktory.
Fred Larson,
6
Tak, to jest coś, co robisz w wywiadzie, aby
przerazić
1
Z mojego doświadczenia wynika, że ​​nie jest to wcale takie niezwykłe.
@Neil Butterworth: Który?
dirkgently
@Dirk - scenariusz "dowolna funkcja". Nierzadko zdarza się, że jest używany do implementowania pewnych typowych zachowań.