Partager via


Classes abstraites (C++)

Les classes abstraites agissent comme des expressions de concepts généraux dont des classes plus spécifiques peuvent être dérivées. Vous ne pouvez pas créer d’objet d’un type de classe abstraite. Toutefois, vous pouvez utiliser des pointeurs et des références aux types de classes abstraits.

Vous créez une classe abstraite en déclarant au moins une fonction membre virtuelle pure. Il s’agit d’une fonction virtuelle déclarée à l’aide de la syntaxe du spécificateur pur (= 0). Les classes dérivées de la classe abstraite doivent implémenter la fonction virtuelle pure, sinon elles aussi sont des classes abstraites.

Prenons l’exemple présenté dans les fonctions virtuelles. L'objectif de la classe Account est de fournir une fonctionnalité générale, mais les objets de type Account sont trop généraux pour être utiles. Cela signifie qu’il s’agit Account d’un bon candidat pour une classe abstraite :

// deriv_AbstractClasses.cpp
// compile with: /LD
class Account {
public:
   Account( double d );   // Constructor.
   virtual double GetBalance();   // Obtain balance.
   virtual void PrintBalance() = 0;   // Pure virtual function.
private:
    double _balance;
};

La seule différence entre cette déclaration et la précédente vient du fait que PrintBalance est déclaré avec le spécificateur pure (= 0).

Restrictions sur les classes abstraites

Les classes abstraites ne peuvent pas être utilisées pour :

  • Variables ou données membres (vous ne pouvez pas déclarer de variable d’un type de classe abstrait)

  • Types d’arguments (vous ne pouvez pas passer une classe abstraite par valeur en tant que paramètre de fonction)

  • Types de retour de fonction (une fonction ne peut pas retourner une classe abstraite par valeur)

  • Types de conversions explicites (vous ne pouvez pas effectuer de conversion en type de classe abstrait)

Dans chaque cas, vous pouvez utiliser des pointeurs ou des références au type de classe abstrait à la place. Par exemple, une fonction peut prendre AbstractBase& ou AbstractBase* en tant que paramètre, et vous pouvez déclarer des pointeurs ou des références du type de classe abstraite.

Si le constructeur d’une classe abstraite appelle une fonction virtuelle pure, directement ou indirectement, le résultat n’est pas défini. Toutefois, les constructeurs et les destructeurs des classes abstraites peuvent appeler d'autres fonctions membres.

Fonctions virtuelles pures définies

Les fonctions virtuelles pures dans les classes abstraites peuvent être définies ou avoir une implémentation. Vous ne pouvez appeler ces fonctions qu’à l’aide de la syntaxe complète :

abstract-class-name ::function-name()

Les fonctions virtuelles pures définies sont utiles lorsque vous concevez des hiérarchies de classes dont les classes de base incluent des destructeurs virtuels purs. C’est parce que les destructeurs de classe de base sont toujours appelés pendant la destruction d’objets. Prenons l’exemple suivant :

// deriv_RestrictionsOnUsingAbstractClasses.cpp
// Declare an abstract base class with a pure virtual destructor.
// It's the simplest possible abstract class.
class base
{
public:
    base() {}
    // To define the virtual destructor outside the class:
    virtual ~base() = 0;
    // Microsoft-specific extension to define it inline:
//  virtual ~base() = 0 {};
};

base::~base() {} // required if not using Microsoft extension

class derived : public base
{
public:
    derived() {}
    ~derived() {}
};

int main()
{
    derived aDerived; // destructor called when it goes out of scope
}

L’exemple montre comment une extension de compilateur Microsoft vous permet d’ajouter une définition inline à des < virtuels purs />. Vous pouvez également le définir en dehors de la classe à l’aide base::~base() {}de .

Lorsque l’objet sort de l’étendue aDerived , le destructeur de la classe derived est appelé. Le compilateur génère du code pour appeler implicitement le destructeur pour la classe base après le derived destructeur. L’implémentation vide pour la fonction ~base virtuelle pure garantit qu’au moins une implémentation existe pour la fonction. Sans cela, l’éditeur de liens génère une erreur de symbole externe non résolue pour l’appel implicite.

Remarque

Dans l'exemple précédent, la fonction virtuelle pure base::~base est appelée implicitement depuis derived::~derived. Il est également possible d’appeler explicitement des fonctions virtuelles pures à l’aide d’un nom de fonction membre complet. Ces fonctions doivent avoir une implémentation, ou l’appel génère une erreur au moment du lien.

Voir aussi

Héritage