2009-06-10 7 views
28

In C++ ist es legal, eine Implementierung einer rein virtuellen Funktion zu geben:Unter welchen Umständen ist es vorteilhaft, eine Implementierung einer reinen virtuellen Funktion zu geben?

class C 
{ 
public: 
    virtual int f() = 0; 
}; 

int C::f() 
{ 
    return 0; 
} 

Warum würden Sie überhaupt wollen, dies zu tun?

Verwandte Frage: Die C++ faq lite enthält ein Beispiel:

class Funct { 
public: 
    virtual int doit(int x) = 0; 
    virtual ~Funct() = 0; 
}; 

inline Funct::~Funct() { } // defined even though it's pure virtual; it's faster this way; trust me 

Ich verstehe nicht, warum die destructor rein virtuelle deklariert und dann umgesetzt werden; und ich verstehe den Kommentar nicht, warum das schneller sein sollte.

Antwort

23

Deklarierte Destruktoren müssen immer implementiert werden, da die Implementierung sie als Teil der abgeleiteten Objektzerstörung bezeichnet.

Andere rein virtuelle Funktionen können implementiert werden, wenn sie eine nützliche allgemeine Funktionalität bieten, aber immer spezialisiert sein müssen. In dem Fall, in der Regel abgeleitete Klasse Implementierungen einen expliziten Aufruf die Basisimplementierung machen:

void Derived::f() 
{ 
    Base::f(); 

    // Other Derived specific functionality 
} 
Typischerweise

, machen Sie einen Destruktor virtuell, wenn Sie eine Klasse abstrakt machen müssen (dh verhindert nicht abgeleiteten Instanzen werden erstellt) aber die Klasse hat keine anderen Funktionen, die natürlich rein virtuell sind. Ich glaube, das "Vertrauen, dass es schneller ist" bezieht sich auf die Tatsache, dass Destruktoren, die als Teil der Bereinigung von abgeleiteten Objekten aufgerufen werden, keinen vtable-Lookup-Mechanismus verwenden müssen. Im Gegensatz zu typischen virtuellen Funktionsaufrufen kann die Inline-Implementierung genutzt werden .

4

Wenn Sie so allgemeine Funktionalität haben, die abgeleitete Klasse verwenden kann. Aber sie müssen auch andere Arbeit tun.

So die abgeleitete Klasse implementiert die virtuelle Funktion und ruft die zugrunde liegenden Basisversion:

class X: public C 
{ 
    public: 
     virtual int f() 
     { 
      return C::f() + 1; // I am +1 over my parent. 
     } 
}; 
0

Weil es so schlecht gebildet betrachtet ist zu schreiben:

class Funct { 
public: 
    virtual int doit(int x) = 0; 
    virtual ~Funct() = 0 {}; 
}; 

Der Destruktor wird nach wie vor, wenn Sie angerufen werden von dieser Klasse ableiten. Alle Methoden rein virtuell zu deklarieren dient nur der Übersichtlichkeit. Sie könnten es auch so schreiben:

class Funct { 
public: 
    virtual int doit(int x) = 0; 
    virtual ~Funct() {}; 
}; 

Die Klasse wird immer noch abstrakt sein, da mindestens eine Methode rein virtuell ist. Der Destruktor ist auch noch inline.

2

G'day,

In Bezug auf eine Standardimplementierung für eine Member-Funktion in einer Basisklasse deklariert bietet, ist der einzige Grund, warum ich von im Moment denken kann, ist, wo Sie eine Standardimplementierung des Verhaltens zur Verfügung stellen möchten, wie eine mögliche Implementierungswahl für jemanden, der sich auf die Basisklasse spezialisiert hat.

Der Autor der abgeleiteten Klasse kann die vom Basisklassenautor bereitgestellte Standardimplementierung verwenden, anstatt eine eigene spezialisierte Implementierung hinzuzufügen.

Dies ist in der Regel der Fall, in dem Benutzer separate Funktionen zur Bereitstellung einer Schnittstelle und einer Standardimplementierung des Verhaltens ablehnen, aber dennoch eine Trennung zwischen der Standardimplementierung und der zugehörigen Schnittstelle wünschen.

Ah, gerade gesehen @Martin Yorks Beitrag, der ein Beispiel bietet.

Eigentlich, Scott Meyers bespricht dies in seinem Buch "Effective C++". Es ist Artikel 36 in der 1. Ausgabe.

HTH

prost, fand

0

In Bezug auf die Geschwindigkeit des virtuellen Destruktors liegt das daran, dass der Destruktor in der cpp-Datei und nicht im Header definiert ist. Es hat mehr mit Größe als mit Geschwindigkeit zu tun. Es wird im "Large-Scale C++ Software Design" ausführlich erklärt. Leider kann ich mich nicht an alle Details erinnern, aber ich denke, inline virtuelle Funktionen werden in der vtable mehrfach definiert.

Es gibt eine Diskussion hier: Are inline virtual functions really a non-sense?

Verwandte Themen