Namespaces
Variants

Abstract class

From cppreference.net
C++ language
General topics
Flow control
Conditional execution statements
Iteration statements (loops)
Jump statements
Functions
Function declaration
Lambda function expression
inline specifier
Dynamic exception specifications ( until C++17* )
noexcept specifier (C++11)
Exceptions
Namespaces
Types
Specifiers
constexpr (C++11)
consteval (C++20)
constinit (C++20)
Storage duration specifiers
Initialization
Expressions
Alternative representations
Literals
Boolean - Integer - Floating-point
Character - String - nullptr (C++11)
User-defined (C++11)
Utilities
Attributes (C++11)
Types
typedef declaration
Type alias declaration (C++11)
Casts
Memory allocation
Classes
Class-specific function properties
Special member functions
Templates
Miscellaneous

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

Siehe auch