Partie 10: Classes Génériques — Programmation orientée objet en C++

1 446 vues

Publié le

Support material for a continued education course "Introduction to object oriented programming in C++".
In French.

0 commentaire
1 j’aime
Statistiques
Remarques
  • Soyez le premier à commenter

Aucun téléchargement
Vues
Nombre de vues
1 446
Sur SlideShare
0
Issues des intégrations
0
Intégrations
3
Actions
Partages
0
Téléchargements
113
Commentaires
0
J’aime
1
Intégrations 0
Aucune incorporation

Aucune remarque pour cette diapositive

Partie 10: Classes Génériques — Programmation orientée objet en C++

  1. 1. Programmation Orientée Objet en C++ 10ème Partie: Classes Génériques Fabio Hernandez Fabio.Hernandez@in2p3.fr
  2. 2. Vue dEnsemble Notions de base Types, variables, opérateurs Contrôle dexécution Fonctions Mémoire dynamique Qualité du logiciel Evolution du modèle objet Objets et classes Fonctions membres Classes génériques Héritage Polymorphisme Héritage multiple Entrée/sortiePOO en C++: Classes Génériques 314 © 1997-2003 Fabio HERNANDEZ
  3. 3. Table des Matières Motivation Déclaration dune classe générique Utilisation Implémentation des fonctions membres Considérations particulières Fonctions génériques Contraintes Coût vs. Bénéfice RésuméPOO en C++: Classes Génériques 315 © 1997-2003 Fabio HERNANDEZ
  4. 4. Motivation Nous avons étudié les facilités offertes par C++ pour créer des classes permettant de définir des conteneurs dobjets dun même type Un conteneur est un objet qui agit sur une collection de zéro ou plusieurs objets dune classe particulière Les classes List et Queue et les tableaux sont des exemples des classes conteneurs Le type des objets contenus dans un objet de la classe List ou de la classe Queue est float Les services de ces classes (append, prepend, insert, remove,...) ne dépendent pas du type des objets quelles contiennentPOO en C++: Classes Génériques 316 © 1997-2003 Fabio HERNANDEZ
  5. 5. Motivation (suite) Supposons que nous voulons créer une List dobjets de type char Une possible solution consiste à dupliquer le code déjà écrit pour la classe List en faisant les modifications pour que les objets contenus soient de type char et pas float il faudrait aussi renommer les classes (FloatList, CharList,...) cette solution pose des problèmes pour la maintenance du code Une autre possible solution est dutiliser les facilités de définition de macros du pré-processeur pour générer le code nécessaire sur demande du programmeur problèmes de maintenance particulièrement inélégantPOO en C++: Classes Génériques 317 © 1997-2003 Fabio HERNANDEZ
  6. 6. Motivation (suite) C++ fournit un mécanisme permettant de définir des classes (et des fonctions) génériques (paramétrables) Lidée est décrire des "moules" permettant de construire dautres classes particulièrement utile pour les conteneurs le paramètre de la classe correspond au type des objets contenus En C++ cette facilité est connue sous le nom de template Nous allons étudier à nouveau la classe List et la modifier de façon à ce quelle devienne génériquePOO en C++: Classes Génériques 318 © 1997-2003 Fabio HERNANDEZ
  7. 7. Contrôle dAvancement Motivation Déclaration dune classe générique Utilisation Implémentation des fonctions membres Considérations particulières Fonctions génériques Contraintes Coût vs. Bénéfice RésuméPOO en C++: Classes Génériques 319 © 1997-2003 Fabio HERNANDEZ
  8. 8. Déclaration #if !defined(LIST_H_INCLUDED) #define LIST_H_INCLUDED Item est le template <class Item> paramètre de class List { la classe List public: // Constructors/Destructor List(); List(int initialCapacity); List(const List& aList); ~List(); // Modifiers bool append(Item anItem); bool prepend(Item anItem); bool insert(Item anItem, int position); bool remove(Item anItem);POO en C++: Classes Génériques 320 © 1997-2003 Fabio HERNANDEZ
  9. 9. Déclaration (suite) bool removeAll(Item anItem); bool replace(int position, Item anItem); bool replaceAll(Item item1, Item item2); void clear(); // Selectors int length() const; int occurrences(Item anItem) const; int position(Item anItem) const; Item itemAt(int position) const; Item first() const; Item last() const; bool isEqual(const List& aList) const; bool isEmpty() const;POO en C++: Classes Génériques 321 © 1997-2003 Fabio HERNANDEZ
  10. 10. Déclaration (suite) private: // Data members Item* data_; int capacity_; int length_; // Help functions void resize(); }; #endif // LIST_H_INCLUDEDPOO en C++: Classes Génériques 322 © 1997-2003 Fabio HERNANDEZ
  11. 11. Contrôle dAvancement Motivation Déclaration dune classe générique Utilisation Implémentation des fonctions membres Considérations particulières Fonctions génériques Contraintes Coût vs. Bénéfice RésuméPOO en C++: Classes Génériques 323 © 1997-2003 Fabio HERNANDEZ
  12. 12. Utilisation Pour utiliser (créer une instance d) une classe générique il faut fournir les paramètres nécessaires Fichier main.cpp #include "List.h" void main() { Création d’une List<char> alphabet; instance de la classe alphabet.append(z); générique avec le type alphabet.prepend(a); primitif char comme paramètre if (alphabet.isEmpty()) ... cout << "Length = " << alphabet.length() << endl; ... }POO en C++: Classes Génériques 324 © 1997-2003 Fabio HERNANDEZ
  13. 13. Utilisation (suite) De façon similaire pour les listes des autres types primitifs List<float> hitList; List<int> counterList; ... On peut aussi créer des instances des classes génériques avec comme paramètre dautres classes #include "Point.h" #include "List.h" List<Point> vertexList; // A List of Point objectsPOO en C++: Classes Génériques 325 © 1997-2003 Fabio HERNANDEZ
  14. 14. Utilisation (suite) Notez que les instances des classes génériques sont complètement identifiées par le nom de la classe et ses paramètres List<int> counterList; List<char> alphabet; ... // COMPILATION ERROR: counterList and // alphabet are two objets of a different class if (counterList.isEqual(alphabet)) cout << "They are equal" << endl;POO en C++: Classes Génériques 326 © 1997-2003 Fabio HERNANDEZ
  15. 15. Utilisation (suite) Afin de faciliter lécriture, on peut définir des synonymes #include "List.h" Définition dun typedef List<char> CharList; synonyme dune ... classe générique CharList alphabet; alphabet.clear(); for(char letter=a; letter <= z; ++letter) alphabet.append(letter); ...POO en C++: Classes Génériques 327 © 1997-2003 Fabio HERNANDEZ
  16. 16. Contrôle dAvancement Motivation Déclaration dune classe générique Utilisation Implémentation des fonctions membres Considérations particulières Fonctions génériques Contraintes Coût vs. Bénéfice RésuméPOO en C++: Classes Génériques 328 © 1997-2003 Fabio HERNANDEZ
  17. 17. Implémentation Spécificités syntaxiques liées à la "généricité" Exemple template<class Item> Item List<Item>::first() const { assert(length_ > 0); return data_[0]; } template<class Item> inline bool List<Item>::isEmpty() const { return (length_ == 0) ? true : false; }POO en C++: Classes Génériques 329 © 1997-2003 Fabio HERNANDEZ
  18. 18. Implémentation (suite) Limplémentation des fonctions membres doit être contenue (directe ou indirectement) lorsque lon inclut le fichier de linterface Fichier List.h #if !defined(LIST_H_INCLUDED) #define LIST_H_INCLUDED template <class Item> class List { public: ... private: ... };POO en C++: Classes Génériques 330 © 1997-2003 Fabio HERNANDEZ
  19. 19. Implémentation (suite) Fichier List.h (suite) template<class Item> Item List<Item>::first() const { ... } template<class Item> inline bool List<Item>::isEmpty() const { ... } ... #endif // LIST_H_INCLUDEDPOO en C++: Classes Génériques 331 © 1997-2003 Fabio HERNANDEZ
  20. 20. Paramètres des Classes Génériques Spécification de plusieurs paramètres template <class T1, class T2, class T3> class ComplicatedClass { public: ... private: ... }; Création dun objet de cette classe ComplicatedClass<float, int, Point> complicatedObject;POO en C++: Classes Génériques 332 © 1997-2003 Fabio HERNANDEZ
  21. 21. Paramètres des Classes Génériques (suite) Les paramètres peuvent aussi être des expressions template <class Type, int Size> class Buffer { ... }; Utilisation Buffer<double,256> littleBuffer; Buffer<char,1024*10> bigBuffer; const int MaxSize = 100; Buffer<bool,MaxSize> answerBuffer;POO en C++: Classes Génériques 333 © 1997-2003 Fabio HERNANDEZ
  22. 22. Contrôle dAvancement Motivation Déclaration dune classe générique Utilisation Implémentation des fonctions membres Considérations particulières Fonctions génériques Contraintes Coût vs. Bénéfice RésuméPOO en C++: Classes Génériques 334 © 1997-2003 Fabio HERNANDEZ
  23. 23. Considérations Particulières Cette implémentation fonctionne-t-elle aussi bien pour les objets complexes que pour les objets des types primitifs? template <class Item> bool List<Item>::append(Item anItem) { if (length_ == capacity_) resize(); data_[length_] = anItem; ++length_; return true; }POO en C++: Classes Génériques 335 © 1997-2003 Fabio HERNANDEZ
  24. 24. Considérations Particulières (suite) Nous devrions plutôt la modifier comme template <class Item> bool List<Item>::append(const Item& anItem) { if (length_ == capacity_) resize(); data_[length_] = anItem; ++length_; return true; } De façon similaire pour les autres fonctions membresPOO en C++: Classes Génériques 336 © 1997-2003 Fabio HERNANDEZ
  25. 25. Contrôle dAvancement Motivation Déclaration dune classe générique Utilisation Implémentation des fonctions membres Considérations particulières Fonctions génériques Contraintes Coût vs. Bénéfice RésuméPOO en C++: Classes Génériques 337 © 1997-2003 Fabio HERNANDEZ
  26. 26. Fonctions Génériques Syntaxe similaire à celle des classes template <class Type> Type min(Type a, Type b) { return (a < b) ? a : b; } template <class Item> ostream& operator<<(ostream& stream, const List<Item>& aList) { ... return stream; }POO en C++: Classes Génériques 338 © 1997-2003 Fabio HERNANDEZ
  27. 27. Contrôle dAvancement Motivation Déclaration dune classe générique Utilisation Implémentation des fonctions membres Considérations particulières Fonctions génériques Contraintes Coût vs. Bénéfice RésuméPOO en C++: Classes Génériques 339 © 1997-2003 Fabio HERNANDEZ
  28. 28. Contraintes Limplémentation des fonctions membres dune classe générique impose des contraintes sur les classes utilisées comme paramètre du template Exemple la fonction membre int List<Item>::position(const Item& anItem) const suppose que la classe Item fournit lopérateur dégalité la fonction membre int List<Item>::append(const Item& anItem) suppose que la classe Item fournit lopérateur daffectation Linstance ne pourra pas être créée si ces suppositions ne sont pas satisfaites au moment de la compilationPOO en C++: Classes Génériques 340 © 1997-2003 Fabio HERNANDEZ
  29. 29. Contrôle dAvancement Motivation Déclaration dune classe générique Utilisation Implémentation des fonctions membres Considérations particulières Fonctions génériques Contraintes Coût vs. Bénéfice RésuméPOO en C++: Classes Génériques 341 © 1997-2003 Fabio HERNANDEZ
  30. 30. Coût vs. Bénéfice Avantages mécanisme très puissant Inconvénients syntaxe dissuasive pas encore (bien) supporté par quelques compilateurs temps de compilation/édition de liens augmenté taille de lexécutable augmentéePOO en C++: Classes Génériques 342 © 1997-2003 Fabio HERNANDEZ
  31. 31. Résumé Les classes génériques servent pour décrire des conteneurs indépendamment du type des objets contenus Le client de la classe générique doit fournir les types nécessaires pour la création de l’instance de la classe générique Limplémentation des classes génériques suppose une attention particulière puisque le type de chaque paramètre nest pas connu à priori Bien que normalisé, ce mécanisme nest pas encore supporté par tous les compilateursPOO en C++: Classes Génériques 343 © 1997-2003 Fabio HERNANDEZ

×