Namensräume
Varianten
Aktionen

Abstrakte Klasse

Von cppreference.com
< cpp‎ | Sprache
 
 
C++ Sprache
Allgemeine Themen
Kontrollfluss
Bedingte Ausführungsaussagen
if
Iterationsanweisungen (Schleifen)
for
Bereichs-for (C++11)
Sprunganweisungen
Funktionen
Funktionsdeklaration
Lambda-Funktionsausdruck
inline-Spezifizierer
Dynamische Ausnahmespezifikationen (bis C++17*)
noexcept-Spezifizierer (C++11)
Ausnahmen
Namensräume
Typen
Spezifizierer
const/volatile
decltype (C++11)
auto (C++11)
constexpr (C++11)
consteval (C++20)
constinit (C++20)
Speicherdauer-Spezifizierer
Initialisierung
Ausdrücke
Alternative Darstellungen
Literale
Boolesch - Ganzzahl - Gleitkommazahl
Zeichen - String - nullptr (C++11)
Benutzerdefinierte (C++11)
Dienstprogramme
Attribute (C++11)
Typen
typedef-Deklaration
Typalias-Deklaration (C++11)
Umwandlungen
Speicherzuweisung
Klassen
Klassenspezifische Funktionseigenschaften
explicit (C++11)
static

Spezielle Member-Funktionen
Templates
Sonstiges
 
 

Definiert einen abstrakten Typ, der nicht instanziiert werden kann, aber als Basisklasse verwendet werden kann.

Inhalt

[bearbeiten] Syntax

Eine rein virtuelle Funktion ist eine virtuelle Funktion, deren Deklarator die folgende Syntax aufweist:

Deklarator virt-Spezifizierer (optional) = 0

Hier ist die Sequenz = 0 als Rein-Spezifizierer bekannt und erscheint entweder unmittelbar nach dem Deklarator oder nach dem optionalen virt-Spezifizierer (override oder final).

Rein-Spezifizierer kann nicht in einer Member-Funktionsdefinition oder friend Deklaration erscheinen.

struct Base
{
    virtual int g();
    virtual ~Base() {}
};
 
struct A : Base
{
    // OK: declares three member virtual functions, two of them pure
    virtual int f() = 0, g() override = 0, h();
 
    // OK: destructor can be pure too
    ~A() = 0;
 
    // Error: pure-specifier on a function definition
    virtual int b() = 0 {}
};

Eine abstrakte Klasse ist eine Klasse, die mindestens eine Funktion definiert oder erbt, für die der finale Überschreiber rein virtuell ist.

[bearbeiten] Erklärung

Abstrakte Klassen werden verwendet, um allgemeine Konzepte (z. B. Shape, Animal) darzustellen, die als Basisklassen für konkrete Klassen (z. B. Circle, Dog) verwendet werden können.

Es können keine Objekte einer abstrakten Klasse erstellt werden (außer Basis-Subobjekte einer von ihr abgeleiteten Klasse) und es können keine nicht-statischen Datenmember 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 am Punkt der Definition und des Funktionsaufrufs überprüft wird, da am Punkt 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;  // pure virtual
}; // "Abstract" is abstract
 
struct Concrete : Abstract
{
    void f() override {}   // non-pure virtual
    virtual void g();      // non-pure virtual
}; // "Concrete" is non-abstract
 
struct Abstract2 : Concrete
{
    void g() override = 0; // pure virtual overrider
}; // "Abstract2" is abstract
 
int main()
{
    // Abstract a;   // Error: abstract class
    Concrete b;      // OK
    Abstract& a = b; // OK to reference abstract base
    a.f();           // virtual dispatch to Concrete::f()
    // Abstract2 a2; // Error: abstract class (final overrider of g() is pure)
}

Die Definition einer rein virtuellen Funktion kann bereitgestellt werden (und muss bereitgestellt werden, wenn die rein virtuelle Funktion der Destruktor ist): Die Member-Funktionen der abgeleiteten Klasse können die rein virtuelle Funktion der abstrakten Basisklasse frei mit einem qualifizierten Funktionsnamen aufrufen. Diese Definition muss außerhalb des Klassenrumpfes bereitgestellt werden (die Syntax einer Funktionsdeklaration erlaubt weder den rein-spezifizierer = 0 noch einen Funktionsrumpf).

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; // pure virtual
    virtual void g() {}   // non-pure virtual
 
    ~Abstract()
    {
        g();           // OK: calls Abstract::g()
        // f();        // undefined behavior
        Abstract::f(); // OK: non-virtual call
    }
};
 
// definition of the pure virtual function
void Abstract::f()
{
    std::cout << "A::f()\n";
}
 
struct Concrete : Abstract
{
    void f() override
    {
        Abstract::f(); // OK: calls pure virtual function
    }
 
    void g() override {}
 
    ~Concrete()
    {
        g(); // OK: calls Concrete::g()
        f(); // OK: calls Concrete::f()
    }
};

[bearbeiten] Fehlerberichte

Die folgenden Verhaltensändernden Fehlerberichte wurden rückwirkend auf zuvor veröffentlichte C++-Standards angewendet.

DR angewendet auf Verhalten wie veröffentlicht Korrigiertes Verhalten
CWG 390 C++98 ein undefinierter rein virtueller Destruktor könnte aufgerufen werden in diesem Fall ist eine Definition erforderlich
CWG 2153 C++98 Rein-Spezifizierer konnte in friend Deklarationen erscheinen verboten

[bearbeiten] Siehe auch