Eine reine virtual
Funktion muss in einem abgeleiteten Typ implementiert werden, der direkt instanziiert wird. Der Basistyp kann jedoch weiterhin eine Implementierung definieren. Eine abgeleitete Klasse kann die Basisklassenimplementierung explizit aufrufen (wenn Zugriffsrechte es erlauben) durch eine voll scoped Namen (durch den Aufruf A::f()
in Ihrem Beispiel - wenn A::f()
waren public
oder protected
). Etwas wie:
class B : public A {
virtual void f() {
// class B doesn't have anything special to do for f()
// so we'll call A's
// note that A's declaration of f() would have to be public
// or protected to avoid a compile time problem
A::f();
}
};
Der Anwendungsfall, den ich mir auf Anhieb vorstellen kann, ist, wenn es ein mehr oder weniger vernünftiges Standardverhalten gibt, der Klassendesigner jedoch möchte, dass das Standardverhalten nur explizit aufgerufen wird. Es kann auch der Fall sein, dass abgeleitete Klassen immer ihre eigene Arbeit ausführen sollen, aber auch einen gemeinsamen Satz von Funktionen aufrufen können.
Beachten Sie, dass es, obwohl es von der Sprache erlaubt ist, nicht häufig verwendet wird (und die Tatsache, dass dies möglich ist, scheint die meisten C ++ - Programmierer, selbst erfahrene, zu überraschen).
deported
. (entweder in .inl oder .cpp, um auf gängige Methoden zur Benennung von Dateien zu verweisen).Um klar zu sein, verstehen Sie falsch, was = 0; nach einer virtuellen Funktion bedeutet.
= 0 bedeutet, dass abgeleitete Klassen eine Implementierung bereitstellen müssen, nicht dass die Basisklasse keine Implementierung bereitstellen kann.
Wenn Sie eine virtuelle Funktion als rein (= 0) markieren, macht es in der Praxis wenig Sinn, eine Definition anzugeben, da sie nur aufgerufen wird, wenn dies ausdrücklich über Base :: Function (...) geschieht oder wenn die Der Basisklassenkonstruktor ruft die betreffende virtuelle Funktion auf.
quelle
Der Vorteil besteht darin, dass abgeleitete Typen gezwungen werden, die Methode weiterhin zu überschreiben, aber auch eine Standard- oder additive Implementierung bereitgestellt werden.
quelle
Wenn Sie Code haben, der von der ableitenden Klasse ausgeführt werden soll, aber nicht direkt ausgeführt werden soll - und Sie möchten, dass er überschrieben wird.
Ihr Code ist korrekt, obwohl dies insgesamt keine häufig verwendete Funktion ist und normalerweise nur angezeigt wird, wenn Sie versuchen, einen reinen virtuellen Destruktor zu definieren. In diesem Fall müssen Sie eine Implementierung bereitstellen. Das Lustige ist, dass Sie, sobald Sie von dieser Klasse abgeleitet sind, den Destruktor nicht mehr überschreiben müssen.
Daher ist die einzig sinnvolle Verwendung von reinen virtuellen Funktionen die Angabe eines reinen virtuellen Destruktors als "nicht endgültiges" Schlüsselwort.
Der folgende Code ist überraschend korrekt:
quelle
Du müsstest zum Beispiel einem reinen virtuellen Destruktor einen Körper geben :)
Lesen Sie: http://cplusplus.co.il/2009/08/22/pure-virtual-destructor/
(Link defekt, Archiv benutzen)
quelle
Ja das ist korrekt. In Ihrem Beispiel erben Klassen, die von A abgeleitet sind, sowohl die Schnittstelle f () als auch eine Standardimplementierung. Sie erzwingen jedoch abgeleitete Klassen, um die Methode f () zu implementieren (auch wenn nur die von A bereitgestellte Standardimplementierung aufgerufen werden soll).
Scott Meyers diskutiert dies in Effective C ++ (2. Ausgabe) Punkt 36 Unterscheiden Sie zwischen der Vererbung der Schnittstelle und der Vererbung der Implementierung. Die Artikelnummer hat sich möglicherweise in der letzten Ausgabe geändert.
quelle
Reine virtuelle Funktionen mit oder ohne Körper bedeuten einfach, dass die abgeleiteten Typen ihre eigene Implementierung bereitstellen müssen.
Reine virtuelle Funktionskörper in der Basisklasse sind nützlich, wenn Ihre abgeleiteten Klassen Ihre Basisklassenimplementierung aufrufen möchten.
quelle
Die 'virtuelle Leere foo () = 0;' Syntax bedeutet nicht, dass Sie foo () nicht in der aktuellen Klasse implementieren können. Dies bedeutet auch nicht, dass Sie es in abgeleiteten Klassen implementieren müssen . Bevor Sie mich schlagen, lassen Sie uns das Diamantproblem beobachten: (Impliziter Code, wohlgemerkt).
Der Aufruf von obj-> foo () führt nun zu B :: foo () und dann zu C :: bar ().
Sie sehen ... reine virtuelle Methoden müssen nicht in abgeleiteten Klassen implementiert werden (foo () hat keine Implementierung in Klasse C - Compiler wird kompiliert) In C ++ gibt es viele Lücken.
Hoffe ich konnte helfen :-)
quelle
C
in Ihrem Beispiel kein Objekt vom Typ instanziieren . Sie können ein Objekt vom Typ instanziiert ,D
weil es seine Umsetzung wirdfoo
ausB
.Ein wichtiger Anwendungsfall für eine rein virtuelle Methode mit einem Implementierungskörper ist, wenn Sie eine abstrakte Klasse haben möchten, aber keine geeigneten Methoden in der Klasse haben, um sie rein virtuell zu machen. In diesem Fall können Sie den Destruktor der Klasse rein virtuell machen und dafür die gewünschte Implementierung (sogar einen leeren Körper) einfügen. Als Beispiel:
Diese Technik macht die
Foo
Klasse abstrakt und daher unmöglich, die Klasse direkt zu instanziieren. Gleichzeitig haben Sie keine zusätzliche rein virtuelle Methode hinzugefügt, um dieFoo
Klasse abstrakt zu machen .quelle