2010-07-26 4 views
8

Ich habevirtuellen desctructor auf reine abstrakte Basisklasse

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

GCC besteht darauf, dass ich

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

habe ich sehe nicht, warum. Eine reine Schnittstelle ist alles über die Schnittstelle (duh). Der Destruktor ist Teil der internen Implementierungsdetails eines konkreten Implementierers der Schnittstelle; Es ist nicht Teil der Schnittstelle. Ich verstehe die ganze Slicing-Frage (oder zumindest denke ich, dass ich es tue)

Also meine Frage ist - ist GCC richtig, darauf zu bestehen und wenn ja, warum?

+0

Sie sprechen über Destruktoren, aber Ihr Code zeigt einen Konstruktor. Um was geht es? –

+0

@mmyers, reparierte es. –

+1

Regel 1 der Programmierung: Der Compiler ist immer richtig. Regel 2 der Programmierung: Wenn der Compiler falsch ist, gilt Regel 1. –

Antwort

19

Gemäß der C++ Spezifikation, ja.

Sie müssen die destructor virtuelle weil sonst zu erklären, später

IMyInterface * ptr = getARealOne(); 
    delete ptr; 

den destructor auf der abgeleiteten Klasse nicht nennen (weil der Destruktor nicht in der VTable ist)

Es muss sei nicht-rein, weil Basisklassen-Destruktoren immer vom Unterklassen-Destruktor aufgerufen werden.

Um weiter zu erklären, C++ hat kein Konzept einer Schnittstelle in der gleichen Weise wie Java oder C#. Es ist nur eine Konvention, nur rein virtuelle Methoden zu verwenden und sich das als Schnittstelle vorzustellen. Die anderen Regeln über C++ - Destruktoren machen es notwendig, dass sie nicht-rein sind, was die Ähnlichkeit mit Interfaces in anderen Sprachen bricht, aber diese Sprachen existierten zum Zeitpunkt, zu dem diese Regeln gemacht wurden, nicht.

+4

Nitpick - Ich denke, Sie können es rein virtuell machen, wenn Sie untergeordnete Klassen benötigen, um es zu implementieren. Sie müssen jedoch aus den von Ihnen angegebenen Gründen eine Implementierung bereitstellen. –

+0

Ich glaube nicht - es wird heißen, also besser eine Definition haben. Ich habe es nicht ausprobiert, aber in der Regel wird ein pure-virtual vom Compiler implementiert, indem eine Fehlerfunktion in das VTable eingefügt wird, um zu beschweren, dass es aufgerufen wurde. Vielleicht könnte ich mir einen Sonderfall für Destruktoren vorstellen, aber ich bin mir ziemlich sicher, dass das nicht das ist, was die Spezifikation sagt (nicht 100%) –

+0

@Lou Franco: Reine virtuelle Funktionen können Definitionen haben. –

3

Wenn Sie das virtuelle Tor in der Basisklasse nicht deklarieren, führt das Löschen von Objekten abgeleiteter Klassen durch einen Zeiger auf die Basisklasse zum Aufruf des falschen Destruktors und damit zu undefiniertem Verhalten und Ressourcenverlust.

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 kann nicht frei sein, weil es nie neu war. Der Speicher, den er benutzt, wird jedoch nicht ohne den virtuellen Destruktor an das System zurückgegeben. –