#include #include #include #include // definition du type booleen typedef char booleen; #define VRAI 1 #define FAUX 0 class listable; // déclaration de la classe patron liste template class liste : public listable { public : // constructeurs liste(); liste(const liste&); // méthode permettant l'ajout d'un élément à la liste booleen ajoute (T); // operateur de sortie sur flot friend ostream& operator << (ostream&,const liste); // operateur d'assignation liste operator = (const liste); // fonction d'affichage ostream& affiche(ostream&); // fonction de clonage listable* clone(); // destructeur ~liste(); private : // la liste est ici implémentée sous forme d'une liste chaînée // définition d'un maillon de la liste struct maillon { T valeur; maillon* suivant; }; // pointeur de début de liste maillon* debut_liste; }; // déclaration de la classe de base virtuelle listable pour les listes hétérogènes class listable { public : // constructeur listable(); // methode d'affichage virtual ostream& affiche(ostream&) = 0; // methode fournissant un clone virtual listable* clone() = 0; // destructeur virtual ~listable() = 0; }; // définition des méthodes de la classe liste // // constructeur sans argument template liste::liste() { debut_liste = NULL; } // constructeur de recopie template liste::liste(const liste& source) { maillon *index,*nouveau; debut_liste = NULL; for (index=source.debut_liste; index!=NULL; index=index->suivant) { if ((nouveau = new maillon) == NULL) { cout << "Erreur : espace memoire insuffisant" << endl; exit(1); } nouveau->valeur = index->valeur; nouveau->suivant = debut_liste; debut_liste = nouveau; } } // methode d'ajout d'un élément à la liste template booleen liste::ajoute(T element) { maillon *nouveau; if ((nouveau = new maillon) == NULL) { return FAUX; } nouveau->valeur = element; nouveau->suivant = debut_liste; debut_liste = nouveau; return VRAI; } // surcharge de l'operateur de sortie sur flot template ostream& operator << (ostream& flot,const liste list) { liste::maillon *index; flot << "( " ; for (index=list.debut_liste; index!=NULL; index=index->suivant) { flot << index->valeur << " "; } flot << ")"; return flot; } // operateur d'assignation template liste liste::operator = (const liste source) { // si la liste source est la même que la liste cible, on ne fait rien if (this == &source) { return *this; } // destruction des maillons de l'ancienne liste maillon *index, *suivant_index; index = debut_liste; while(index!=NULL) { suivant_index=index->suivant; delete index; index = suivant_index; } // copie de la liste source maillon *nouveau; debut_liste = NULL; for(index=source.debut_liste; index != NULL; index=index->suivant) { if ((nouveau=new maillon) == NULL) { cout << " espace mémoire insuffisant " << endl; exit(1); } nouveau->valeur = index->valeur; nouveau->suivant = debut_liste; debut_liste = nouveau; } return *this; } template ostream& liste::affiche(ostream& flot) { return flot << *this; } template listable* liste::clone() { liste* nouvelle = new liste(*this); return (listable*)nouvelle; } // destructeur template liste::~liste() { maillon *index,*suivant_index; index = debut_liste; while(index!=NULL) { suivant_index = index->suivant; delete index; index = suivant_index; } } // définition particulière pour les listes hétérogènes // constructeur de recopie liste::liste(const liste& source) { maillon *index,*nouveau; debut_liste = NULL; for (index=source.debut_liste; index!=NULL; index=index->suivant) { if ((nouveau = new maillon) == NULL) { cout << "Erreur : espace mémoire insuffisant" << endl; exit(1); } if ((nouveau->valeur = index->valeur->clone()) == NULL) { cout << "Erreur : problème dans la recopie de la liste" << endl; exit(1); } nouveau->suivant = debut_liste; debut_liste = nouveau; } } // methode d'ajout d'un élément à la liste booleen liste::ajoute(listable* element) { maillon *nouveau; if ((nouveau = new maillon) == NULL) { return FAUX; } if ((nouveau->valeur = element->clone()) == NULL) { cout << "Erreur : probleme dans la recopie de la liste" << endl; return FAUX; } nouveau->suivant = debut_liste; debut_liste = nouveau; return VRAI; } // surcharge de l'operateur de sortie sur flot ostream& operator << (ostream& flot,const liste list) { liste::maillon *index; flot << "( " ; for (index=list.debut_liste; index!=NULL; index=index->suivant) { index->valeur->affiche(flot) << " "; } flot << ")"; return flot; } // operateur d'assignation liste liste::operator = (const liste source) { // si la liste source est la même que la liste cible, on ne fait rien if (this == &source) { return *this; } // destruction des maillons de l'ancienne liste maillon *index, *suivant_index; index = debut_liste; while(index!=NULL) { suivant_index=index->suivant; delete index->valeur; delete index; index = suivant_index; } // copie de la liste source maillon *nouveau; debut_liste = NULL; for(index=source.debut_liste; index != NULL; index=index->suivant) { if ((nouveau=new maillon) == NULL) { cout << " espace mémoire insuffisant " << endl; exit(1); } if ((nouveau->valeur = index->valeur->clone()) == NULL) { cout << "Erreur : problème dans la recopie de la liste" << endl; exit(1); } nouveau->suivant = debut_liste; debut_liste = nouveau; } return *this; } // destructeur template liste::~liste() { maillon *index,*suivant_index; index = debut_liste; while(index!=NULL) { suivant_index = index->suivant; delete index->valeur; delete index; index = suivant_index; } } // fin de la définition de la classe liste // // définition des méthodes de la classe listable // // constructeur listable::listable() {} //destructeur listable::~listable() {} // fin de la définiton de la classe listable // // declaration de la classe INT, équivalenye aux entiers class INT : public listable { public : // constructeur INT(int); // operateur de conversion operator int(); // methode d'affichage ostream& affiche(ostream&); // methode fournissant un clone listable* clone(); // destructeur ~INT(); private : int valeur; }; // definition des methodes de la classe INT // // constructeur INT::INT(int entier) { valeur = entier; } // operateur de conversion INT::operator int() { return valeur; } // methode d'affichage ostream& INT::affiche(ostream& flot) { return flot << valeur; } // methode donnant un clone listable* INT::clone() { INT* nouveau; nouveau = new INT(valeur); return nouveau; } // destructeur INT::~INT() {} // fin de la définition de la classe INT // // declaration de la classe CHAR, équivalente aux chaines de caractères class CHAR : public listable { public : // constructeur CHAR(char*); // operateur de conversion operator char*(); // methode d'affichage ostream& affiche(ostream&); // methode fournissant un clone listable* clone(); // destructeur ~CHAR(); private : char* valeur; }; // definition des methodes de la classe CHAR // // constructeur CHAR::CHAR(char* chaine) { if ((valeur = new char[strlen(chaine)+1]) == NULL) { cout << "Erreur : espace mémoire insuffisant" << endl; exit(1); } strcpy (valeur,chaine); } // operateur de conversion CHAR::operator char*() { return valeur; } // methode d'affichage ostream& CHAR::affiche(ostream& flot) { return flot << valeur; } // methode donnant un clone listable* CHAR::clone() { CHAR* nouveau; nouveau = new CHAR(valeur); return nouveau; } // destructeur CHAR::~CHAR() { delete valeur; } // fin de la définition de la classe INT // // programme principal main() { liste liste1,liste2; for (int index=0; index<10; index++) { liste1.ajoute(&INT(index)); liste2.ajoute(&INT(index)); } liste1.ajoute(&CHAR("chaine")); liste2.ajoute(&liste1); cout << "liste1 : " << liste1 << endl; cout << "liste2 : " << liste2 << endl; return (0); } Le résultat à l'éxécution est : liste1 : ( 0 1 2 3 4 5 6 7 8 9 chaine ) liste2 : ( 0 1 2 3 4 5 6 7 8 9 ( 0 1 2 3 4 5 6 7 8 9 chaine ) )