Solution de l’exercice 8.4

On peut bien sûr créer un opérateur d’affectation pour chaque classe concrète, mais cela ne permet pas de faire des affectations de l’une de ces classes à l’autre. Voici une solution à ce problème, basée sur la remarque simple que les méthodes de liste permettent de connaître entièrement le contenu d’une liste, et donc d’en construire une copie :

class liste {       // classe  abstraite     // ...     virtual liste& operator=(liste&) = 0;     };class listech : public liste {     // ...     listech(liste& ls) { nombre = 0; *this = ls; }     listech(listech& lc) { nombre = 0; *this = lc; }     liste& operator=(liste&);     };class listetab : public liste {     /  /...     listetab(liste& ls) { nombre = 0; *this = ls; }     listetab(listetab& lt) { nombre = 0; *this = lt;}     liste& operator=(liste&);     };liste& listech::operator=(liste&  ls)// copie une liste dans this{     supprime(nombre);     int reste = ls.nombre_elt();     if (!reste) return *this;     noeud *np = 0;     while ( (np = new noeud(ls.valeur(),              courant = np)) && (reste--) ) {          ls.avance();          nombre++;          }     ls.avance(reste);    // rétablir début     if (np) courant = np->suivant();     return *this;}liste& listetab::operator=(liste&  ls)// copie la liste dans this{     supprime(nombre);     if ( !ls.nombre_elt() ||         !(tab = new element[ls.nombre_elt()]) )             return *this;     courant = tab;     nombre = ls.nombre_elt();     for (int i = nombre; i; i--) {         *courant++ = ls.valeur();         ls.avance();         }     courant = tab;     return *this;}

On notera que dans le cas de la classe listech par exemple, il faut définir un constructeur de copie pour un argument de liste& et un pour un argument listech&, bien qu’il y ait une conversion automatique de la seconde classe vers la première ; en effet, le premier constructeur avec son argument liste& n’est pas considéré comme un constructeur de copie par C++, puisqu’il n’inclut aucun argument de type listech& ; de ce fait, le compilateur fournit un constructeur implicite qui fait une copie membre à membre, ce qui n’est pas souhaitable ici. Le même raisonnement vaut pour listetab évidemment.

Remarquer également que la copie n’est pas parfaitement identique dans ses effets dans les deux cas, s’il n’y a pas assez de mémoire : listech recopie tout ce qui est possible, tandis que listetab ne recopie rien.


Retour au texte.