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

Définit un type abstrait qui ne peut pas être instancié, mais peut être utilisé comme classe de base.

Table des matières

Syntaxe

Une fonction virtuelle pure est une fonction virtuelle dont le déclarateur a la syntaxe suivante :

declarateur spécificateur-virtuel  (optionnel) = 0

Ici, la séquence = 0 est connue sous le nom de pure-specifier , et apparaît soit immédiatement après le declarator , soit après le virt-specifier optionnel ( override ou final ).

pure-specifier ne peut pas apparaître dans une définition de fonction membre ou une déclaration friend .

struct Base
{
    virtual int g();
    virtual ~Base() {}
};
struct A : Base
{
    // OK : déclare trois fonctions membres virtuelles, dont deux pures
    virtual int f() = 0, g() override = 0, h();
    // OK : le destructeur peut également être pur
    ~A() = 0;
    // Erreur : spécificateur pur sur une définition de fonction
    virtual int b() = 0 {}
};

Une classe abstraite est une classe qui définit ou hérite d'au moins une fonction pour laquelle le remplacement final est purement virtuel .

Explication

Les classes abstraites sont utilisées pour représenter des concepts généraux (par exemple, Shape, Animal), qui peuvent être utilisés comme classes de base pour des classes concrètes (par exemple, Circle, Dog).

Aucun objet d'une classe abstraite ne peut être créé (sauf pour les sous-objets de base d'une classe dérivée de celle-ci) et aucun membre de données non statique dont le type est une classe abstraite ne peut être déclaré.

Les types abstraits ne peuvent pas être utilisés comme types de paramètres, comme types de retour de fonction, ou comme type d'une conversion explicite (notez que cela est vérifié au point de définition et d'appel de fonction, car au point de déclaration de fonction les types de paramètres et de retour peuvent être incomplets).

Les pointeurs et les références vers une classe abstraite peuvent être déclarés.

struct Abstract
{
    virtual void f() = 0;  // virtuelle pure
}; // "Abstract" est abstraite
struct Concrete : Abstract
{
    void f() override {}   // virtuelle non-pure
    virtual void g();      // virtuelle non-pure
}; // "Concrete" est non-abstraite
struct Abstract2 : Concrete
{
    void g() override = 0; // redéfinition virtuelle pure
}; // "Abstract2" est abstraite
int main()
{
    // Abstract a;   // Erreur : classe abstraite
    Concrete b;      // OK
    Abstract& a = b; // OK pour référencer la base abstraite
    a.f();           // dispatch virtuel vers Concrete::f()
    // Abstract2 a2; // Erreur : classe abstraite (la redéfinition finale de g() est pure)
}

La définition d'une fonction virtuelle pure peut être fournie (et doit l'être si la fonction virtuelle pure est le destructeur ) : les fonctions membres de la classe dérivée sont libres d'appeler la fonction virtuelle pure de la classe de base abstraite en utilisant l'identifiant qualifié de fonction. Cette définition doit être fournie en dehors du corps de la classe (la syntaxe d'une déclaration de fonction ne permet pas à la fois le spécificateur pur = 0 et un corps de fonction).

Effectuer un appel virtuel à une fonction virtuelle pure depuis un constructeur ou le destructeur d'une classe abstraite est un comportement indéfini (qu'elle ait une définition ou non).

struct Abstract
{
    virtual void f() = 0; // virtuelle pure
    virtual void g() {}   // virtuelle non-pure
    ~Abstract()
    {
        g();           // OK : appelle Abstract::g()
        // f();        // comportement indéfini
        Abstract::f(); // OK : appel non-virtuel
    }
};
// définition de la fonction virtuelle pure
void Abstract::f()
{
    std::cout << "A::f()\n";
}
struct Concrete : Abstract
{
    void f() override
    {
        Abstract::f(); // OK : appelle la fonction virtuelle pure
    }
    void g() override {}
    ~Concrete()
    {
        g(); // OK : appelle Concrete::g()
        f(); // OK : appelle Concrete::f()
    }
};

Rapports de défauts

Les rapports de défauts modifiant le comportement suivants ont été appliqués rétroactivement aux normes C++ précédemment publiées.

DR Applicable à Comportement publié Comportement corrigé
CWG 390 C++98 un destructeur virtuel pur non défini pouvait être appelé une définition est requise dans ce cas
CWG 2153 C++98 pure-specifier pouvait apparaître dans les déclarations friend interdit

Voir aussi