2011-08-12 16 views
5
class Base 
{ 
    virtual void foo() = 0; 
    //~Base();  <-- No destructor! 
}; 

Otrzymasz oczywiście Base. Tak, czy C++ mówi, że destruktor generowany przez kompilator z Base musi być wirtualny?Czy destruktor generowany przez kompilator abstrakcyjnej klasy bazowej będzie wirtualny?

Dzięki!

+3

Nie, ale nie mogę podać odniesienia do czegoś standardowego * nie * powiedzmy ... –

+2

Jeśli tylko kompilatory mogą odpowiadać na pytania dotyczące stackoverflow;) – MerickOWA

Odpowiedz

6

Nie, destruktor nie będzie virtual, chyba że oznaczysz go jako taki. Powód jest prosty - wywołania można wykonywać wirtualnie zarówno za pomocą wskaźników, jak i za pośrednictwem referencji, a sposób i czy połączenia są praktycznie niezwiązane z tworzeniem obiektów za pomocą new. Jeśli nie tworzysz obiektów przy użyciu new, nie musisz ich używać, więc nie potrzebujesz wirtualnych destruktorów.

1

Nie, dtor nie ma gwarancji, że jest wirtualny.

Podczas deklarowania klas specjalnie zaprojektowanych do wyprowadzenia z jego dobrej praktyki należy jawnie zadeklarować wirtualnego dtora. Zwykle jest to wadą projektową. W rzeczywistości nie mogę wymyślić przypadku, w którym nie jest to wada projektowa, która pomija wirtualnego dtora z klasy bazowej.

+2

Niektóre klasy mogą być zaprojektowane, aby wywodzić się z, ale nie używany polimorficznie (na przykład 'boost :: noncopyable'). W tym przypadku nie ma sensu dostarczanie wirtualnego destruktora. –

+0

@ Luc: w takim przypadku dobrze jest zabezpieczyć destruktor klasy podstawowej, aby zapobiec niesłusznej, polimorficznej delecji. –

+0

To oczywiście prawda. Myślałem w kategoriach kontekstu pytania, którym była ABC. –

2

Nie. Jest blisko do dowodu, że destruktor nie jest automatycznie wykonane wirtualna:

#include <iostream> 

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

struct Base : BaseBase 
{ 
    virtual void foo() = 0; 
    //~Base();  <-- No destructor! 
}; 

struct Derived : Base { 
    void foo() { std::cout << "foo\n"; } 
    ~Derived() { 
     std::cout << "~Derived\n"; 
    } 
}; 

int main() { 
    Base *p = new Derived(); 
    delete p; 
} 

Ten program rzeczywiście jest zachowanie niezdefiniowane, ale silnie podejrzewa, że ​​na realizację nie drukuje „~ pochodny”. Gdyby Base miał wirtualny destruktor, nie miałby niezdefiniowanego zachowania i wydrukowałby "~ Derived".

Oczywiście nic nie dowodzi standardu. Każda implementacja, na której ją uruchomisz, może być w końcu niezgodna. Ale gdy już wypróbujesz to na kilku, dostaniesz pomysł, że niezależnie od standardu może powiedzieć, musisz określić wirtualny destruktor.

+0

Testowałem w kodekach: http://codepad.org/oMs4Kuye (g ++ 4.1.2) i nie wypisuję "~ Derived" zgodnie z oczekiwaniami. Ani na moim MSVC2008. Dzięki za przykład. –

1

Nie. Klasa może mieć członków wirtualnych, może być wyprowadzona i może nawet zostać przydzielona z new i usunięta z delete bez wirtualnego destruktora.

Do nielegalnego (UB) należy zniszczyć wywoływaną instancję za pomocą deleteza pomocą wskaźnika do bazy, jeśli destruktor nie jest deklarowany jako wirtualny.

Oczywiście nie ma powodu, dla którego nie zadeklarowałbyś wirtualnego destruktora, jeśli twoja klasa ma zostać wyprowadzona.

Powiązane problemy