Classes Abstraites et Fonctions Virtuelles Pures

Les classes abstraites sont utilisées pour créer des entités génériques que vous souhaitez utiliser pour créer des classes dérivées plus spécifiques. Une classe abstraite ne peut être utilisée que comme classe de base pour d'autres classes, c'est pourquoi il est impossible de créer un objet du type d'une classe abstraite.

Une classe qui contient au moins une fonction virtuelle pure est abstraite. Les classes dérivées d'une classe abstraite doivent donc implémenter toutes ses fonctions virtuelles pures, sinon elles seront également des classes abstraites.

Une fonction virtuelle est déclarée "pure" en utilisant le mot-clé pure. Considérons l'exemple de la classe CAnimal, qiu n'est créée que pour fournir des fonctions communes — les objets du type CAnimal sont trop généraux pour un usage pratique. CAnimal est donc un bon exemple pour une classe abstraite :

class CAnimal
  {
public:
                      CAnimal();     // Constructeur
   virtual void       Sound() = 0;   // Une fonction virtuelle pure
private:
   double             m_legs_count;  // Le nombre de pattes d'un animal
  };

Ici Sound() est une fonction virtuelle pure, car elle est déclarée avec le spécificateur de fonction virtuelle PURE (=0).

Les fonctions virtuelles pures ne sont que les fonctions virtuelles déclarées avec le spécificateur PURE : (=NULL) ou (=0). Exemple de déclaration et d'utilisation d'une classe abstraite :

class CAnimal
  {
public:
   virtual void       Sound()=NULL;   // méthode PURE, doit être surchargée dans la classe dérivée, CAnimal est maintenant abstraite et ne peut pas être créée
  };
//--- Dérivé d'une classe abstraite
class CCat : public CAnimal
 {
public:
  virtual void        Sound() { Print("Myau"); } // la fonction PURE est surchargée, CCat n'est pas abstraite et peut être créée
 };
 
//--- Exemples de mauvaise utilisation
new CAnimal;         // Erreur de 'CAnimal' - le compilateur retourne l'erreur "cannot instantiate abstract class"
CAnimal some_animal; // Erreur de 'CAnimal' - le compilateur retourne l'erreur "cannot instantiate abstract class"
 
//--- Exemple d'utilisation correcte
new CCat;  // Aucune erreur - la classe CCat n'est pas abstraite
CCat cat;  // Aucune erreur - la classe CCat n'est pas abstraite

 
Restrictions sur les classes abstraites

Si le constructeur d'une classe abstraite appelle une fonction virtuelle pure (directement ou indirectement), le résultat est indéfini.

//+------------------------------------------------------------------+
//| Une classe de base abstraite                                     |
//+------------------------------------------------------------------+
class CAnimal
  {
public:
   //--- Une fonction virtuelle pure
   virtual void      Sound(void)=NULL;
   //--- Fonction
   void              CallSound(void) { Sound(); }
   //--- Constructeur
   CAnimal()
    {
     //--- Un appel explicite à la méthode virtuelle
     Sound();
     //--- Un appel implicite (en utilisant une 3ème fonction)
     CallSound();
     //--- Un constructeur et/ou un destructeur appelle toujours ses propres fonctions,
     //--- même si elles sont virtuelles et surchargées par une fonction appelée dans une classe dérivée
     //--- Si la fonction appelée est virtuelle pure,
     //--- son appel causera une erreur d'exécution critique : "pure virtual function call"
    }
  };

Cependant, les constructeurs et les destructeurs des classes abstraites peuvent appeler d'autres fonctions membres.