Classes abstraites

Une classe est abstraite lorsque l’une au moins de ses méthodes virtuelles est pure. Pour déclarer une méthode virtuelle pure, il suffit de ne pas donner d’implantation et d’écrire = 0 ; derrière sa déclaration. Seules les fonctions virtuelles peuvent être déclarées pures, sous peine d’erreur (Error : Non-virtual function 'xxx' declared pure).

Lorsqu’une classe est abstraite, elle ne peut être utilisée directement ; en particulier, on ne peut pas déclarer d’objets de cette classe, ni d’arguments ou de résultats de fonction. Si vous tentez de le faire, vous obtiendrez Error : Cannot create a variable for abstract class 'xxx', on ne peut pas créer une variable de la classe abstraite 'xxx'.

On peut par contre utiliser des références, des pointeurs et dériver de nouvelles classes, et c’est en fait l’usage de ces classes abstraites. Voici comment déclarer une classe abstraite liste, puis les deux classes de listes concrètes identiques à celles du chapitre 6 :

class liste {       // classe  abstraite     protected :     int nombre;     public :     virtual ~liste() { nombre = 0; };     virtual void avance(int combien = 1)  = 0;    // pure     void recule(int combien = 1)         { avance(-combien); }     virtual element& valeur(void) = 0;    // pure     unsigned nombre_elt(void) { return nombre; }     void affiche(unsigned combien = 65535);     virtual int insere(const element&) = 0;    // pure     virtual void supprime(int n = 1) = 0;    // pure     };class listech : public liste {    // liste chaînée     noeud* courant;     public :     listech() { nombre = 0; courant = 0; }     listech(int n, const element*);    // c. avec table     ~listech();     void avance(int combien = 1);     element& valeur(void)         { if (courant) return courant->contenu(); }     int insere(const element&);     void supprime(int n = 1);     };class listetab : public liste {     element *tab, *courant;     public :     listetab() { courant = tab = 0; }     listetab(int n, const element*);    // c. avec table     ~listetab();     void avance(int combien = 1);     element& valeur(void)         { if (courant) return *courant; }     int insere(const element&);     void supprime(int n = 1);     };

La classe liste est abstraite, puisque quatre de ses méthodes ont été déclarées pures. On notera que certaines ne le sont pas : il s’agit essentiellement (et pas par hasard) de celles qui n’étaient pas virtuelles dans notre exemple précédent.

Le petit programme de démonstration reste identique, sauf que le premier élément de listes doit être initialisé en écrivant new listech..., au lieu de new liste.

Les classes abstraites n’ont généralement pas de constructeur, sauf si l’initialisation des membres est un peu compliquée (ici il suffit de mettre la valeur adéquate dans le champ nombre, et les constructeurs de listch et listtab le font). Par contre, il est généralement souhaitable d’y placer un destructeur virtuel, même s’il ne fait rien comme dans notre exemple : on est ainsi certain de la bonne destruction des objets des classes dérivées.

Exercice 8.4

Comment créer un opérateur d’affectation pour les listes ? Et les constructeurs de copie ?

Voir solution

Ce type de classe peut paraître curieux au premier abord. En fait, il est assez pratique, notamment quand, comme dans notre exemple, on souhaite implanter de plusieurs façons différentes une forme d’objet ; l’utilisateur n’a plus alors qu’à choisir celle qu’il préfère. Le seul inconvénient, assez léger, vient de ce qu’il faut utiliser des pointeurs dans ce cas ; cela évite cependant de se tromper en utilisant un tableau de liste alors qu’il faut un tableau de pointeurs.

Précédent Précédent Sommaire Sommaire Suivant Suivant