Abstract class
Definiert einen abstrakten Typ, der nicht instanziiert werden kann, aber als Basisklasse verwendet werden kann.
Inhaltsverzeichnis |
Syntax
Eine pure virtuelle Funktion ist eine virtuelle Funktion , deren Deklarator die folgende Syntax hat:
Deklarator
virt-specifier
(optional)
=
0
|
|||||||||
Hier wird die Sequenz
= 0
als
pure-specifier
bezeichnet und erscheint entweder unmittelbar nach dem
declarator
oder nach dem optionalen
virt-specifier
(
override
oder
final
).
pure-specifier darf nicht in einer Member-Funktionsdefinition oder einer friend -Deklaration erscheinen.
struct Base { virtual int g(); virtual ~Base() {} }; struct A : Base { // OK: deklariert drei virtuelle Memberfunktionen, zwei davon rein virtuell virtual int f() = 0, g() override = 0, h(); // OK: Destruktor kann ebenfalls rein virtuell sein ~A() = 0; // Fehler: Rein-Virtual-Spezifizierer bei einer Funktionsdefinition virtual int b() = 0 {} };
Eine abstrakte Klasse ist eine Klasse, die mindestens eine Funktion definiert oder erbt, für die der endgültige Überschreiber rein virtuell ist.
Erklärung
Abstrakte Klassen werden verwendet, um allgemeine Konzepte darzustellen (zum Beispiel Shape, Animal), die als Basisklassen für konkrete Klassen verwendet werden können (zum Beispiel Circle, Dog).
Von einer abstrakten Klasse können keine Objekte erstellt werden (außer Basis-Subobjekten einer davon abgeleiteten Klasse) und es können keine nicht-statischen Datenelemente deklariert werden, deren Typ eine abstrakte Klasse ist.
Abstrakte Typen können nicht als Parametertypen, als Rückgabetypen von Funktionen oder als Typ einer expliziten Konvertierung verwendet werden (beachten Sie, dass dies an der Stelle der Definition und des Funktionsaufrufs überprüft wird, da an der Stelle der Funktionsdeklaration Parameter- und Rückgabetyp unvollständig sein können).
Zeiger und Referenzen auf eine abstrakte Klasse können deklariert werden.
struct Abstract { virtual void f() = 0; // rein virtuell }; // "Abstract" ist abstrakt struct Concrete : Abstract { void f() override {} // nicht-rein virtuell virtual void g(); // nicht-rein virtuell }; // "Concrete" ist nicht-abstrakt struct Abstract2 : Concrete { void g() override = 0; // rein virtuelle Überschreibung }; // "Abstract2" ist abstrakt int main() { // Abstract a; // Fehler: abstrakte Klasse Concrete b; // OK Abstract& a = b; // OK zur Referenzierung abstrakter Basis a.f(); // virtuelle Weiterleitung an Concrete::f() // Abstract2 a2; // Fehler: abstrakte Klasse (endgültige Überschreibung von g() ist rein) }
Die Definition einer rein virtuellen Funktion kann bereitgestellt werden (und muss bereitgestellt werden, wenn die rein virtuelle Funktion der
Destruktor
ist): Die Memberfunktionen der abgeleiteten Klasse können die rein virtuelle Funktion der abstrakten Basis mittels qualifizierter Funktions-ID aufrufen. Diese Definition muss außerhalb des Klassenkörpers bereitgestellt werden (die Syntax einer Funktionsdeklaration erlaubt nicht sowohl den pure-specifier
= 0
als auch einen Funktionskörper).
Ein virtueller Aufruf einer rein virtuellen Funktion aus einem Konstruktor oder Destruktor der abstrakten Klasse ist undefiniertes Verhalten (unabhängig davon, ob sie eine Definition hat oder nicht).
struct Abstract { virtual void f() = 0; // rein virtuell virtual void g() {} // nicht-rein virtuell ~Abstract() { g(); // OK: ruft Abstract::g() auf // f(); // undefiniertes Verhalten Abstract::f(); // OK: nicht-virtueller Aufruf } }; // Definition der rein virtuellen Funktion void Abstract::f() { std::cout << "A::f()\n"; } struct Concrete : Abstract { void f() override { Abstract::f(); // OK: ruft rein virtuelle Funktion auf } void g() override {} ~Concrete() { g(); // OK: ruft Concrete::g() auf f(); // OK: ruft Concrete::f() auf } };
Fehlerberichte
Die folgenden verhaltensändernden Fehlerberichte wurden rückwirkend auf zuvor veröffentlichte C++-Standards angewendet.
| DR | Angewendet auf | Verhalten wie veröffentlicht | Korrektes Verhalten |
|---|---|---|---|
| CWG 390 | C++98 | ein undefinierter pure virtual Destruktor könnte aufgerufen werden | eine Definition ist in diesem Fall erforderlich |
| CWG 2153 | C++98 | pure-specifier konnte in friend-Deklarationen erscheinen | verboten |