2010-07-26 17 views
8

mamwirtualny desctructor na czystym abstrakcyjnej klasy bazowej

struct IMyInterface 
{ 
    virtual method1() = 0; 
    virtual method2() = 0; 
}; 

GCC twierdzi, że mam

struct IMyInterface 
{ 
    virtual method1() = 0; 
    virtual method2() = 0; 
    virtual ~IMyInterface(){}; 
}; 

Nie widzę dlaczego. Czysty interfejs dotyczy interfejsu (duh). Destruktor jest częścią wewnętrznych szczegółów implementacji konkretnego implementatora interfejsu; nie stanowi części interfejsu. Rozumiem cały problem związany z krojeniem (a przynajmniej tak myślę)

Moje pytanie brzmi - czy GCC ma prawo nalegać na to, a jeśli tak, dlaczego?

+0

Mówisz o destruktorach, ale twój kod pokazuje konstruktor. O co tu chodzi? –

+0

@mmyers, poprawiono. –

+1

Reguła 1 programowania: Kompilator ma zawsze rację. Zasada 2 programowania: Jeśli kompilator jest niewłaściwy, obowiązuje zasada 1. –

Odpowiedz

19

Zgodnie ze specyfikacją C++, tak.

Musisz zadeklarować destruktora wirtualnych, ponieważ w przeciwnym razie, później

IMyInterface * ptr = getARealOne(); 
    delete ptr; 

nie wywołać destruktor w klasie pochodnej (ponieważ destruktor nie jest w vtable)

Trzeba nie są czyste, ponieważ destruktory klasy podstawowej są zawsze wywoływane przez destruktor podklasowy.

Aby wyjaśnić, C++ nie ma koncepcji interfejsu w taki sam sposób jak Java lub C#. To tylko konwencja, aby używać wyłącznie metod czysto wirtualnych i myśleć o tym jako o interfejsie. Inne zasady dotyczące destruktorów C++ sprawiają, że musi być on nieczysty, co rozbija podobieństwo do interfejsów w innych językach, ale te języki nie istniały w czasie, gdy te reguły zostały wprowadzone.

+4

Nitpick - Wydaje mi się, że możesz uczynić go czystym wirtualnym, jeśli chcesz go zaimplementować. Ale nadal musisz podać implementację z powodów, które podałeś. –

+0

Nie sądzę - będzie to nazywane, więc lepiej mieć definicję. Nie próbowałem go, ale zazwyczaj czysto-wirtualny jest zaimplementowany przez kompilator jako wprowadzający funkcję błędu w VTable do narzekania, że ​​został wywołany. Być może mógłbym sobie wyobrazić specjalny przypadek dla destruktorów, ale jestem prawie pewien, że to nie jest to, co mówi spec (nie w 100%). –

+0

@Lou Franco: Czyste wirtualne funkcje mogą mieć definicje. –

3

Jeśli nie zadeklarujesz wirtualnego tytułu w klasie bazowej, usunięcie obiektów klas pochodnych przez wskaźnik do klasy bazowej prowadzi do wywołania niewłaściwego destruktora, a tym samym do nieokreślonego zachowania i wycieku zasobów.

struct A { 

    virtual ~A() {} 

}; 

struct B : A { 

    std::string us_constitution; 
}; 


B* pb = new B(); 
A* pa = pb; 

delete pa; // without the virtual d'tor in the base class, 'B::us_constitution' would never be freed. 
+0

Nitpick: B :: us_constitution nie może być wolny, ponieważ nigdy nie był nowy. Wykorzystana pamięć nie zostanie jednak zwrócona do systemu bez wirtualnego destruktora. –

Powiązane problemy