Introduction à la généricité Une autre approche de programmation * Concept apparu dès les années 70 * Ce n'est pas un concept objet * Les principes objet ne sont pas nécessaires * ...mais proposé par les langages objets * C++, Java, C# * Abstraction d'un ou plusieurs types de données * Structures de données: vecteur, pile, file, liste chaînée... * Algorithmes: chercher, trier, insérer, extraire... * Générique = composant paramétré sur des types Principe (1/2) * Offre une nouvelle manière de factoriser le code * Dans une fonction, les paramètres sont des valeurs * Lors de sa définition, des valeurs sont inconnues * int max(int a,int b) * Au moment de l'appel, ces valeurs sont fixées * max(5,7) ==> a = 5, b = 7 * Dans un générique, les paramètres sont des types * Lors de sa définition, des types sont inconnus * template <class T> T max(T a,T b) * Au moment d'utiliser le générique, ces types sont fixés * max<int>(5,7) ==> T = int Principe (2/2) * Un générique est un modèle * Instanciation = création d'un composant à partir d'un modèle * Instancier un générique ==> fixer le type de ses paramètres * Spécificités en C++ * Génériques appelés "templates" * Fonctions, classes et méthodes peuvent être génériques * Des constantes peuvent aussi être des paramètres * Possibilité de "spécialisation statique" * Une nouvelle forme de polymorphisme * Permet la spécialisation pour certains types de données Exemples * Algorithme de tri * Fonctionne de la même manière sur tout type de données * Entiers, flottants, chaînes, objets d'une classe A... ==> abstraction du type manipulé T * Suppose une relation d'ordre sur le type T ==> opérateur < * C++ permet de définir ("surcharger") l'opérateur pour tout type * Type liste chaînée * Fonctionne de la même manière sur tout type de données ==> abstraction du type manipulé T * Suppose un test d'égalité sur le type T ==> opérateur == Héritage vs. généricité * Les deux approches sont complémentaires * Toutes les deux fournissent une forme de polymorphisme * La généricité agit à la compilation * L'héritage agit à l'exécution * Contribuent toutes les deux à développer du code générique * Toutes les deux font abstraction du type * L'une par un processus de généralisation * L'autre par un mécanisme de paramètre * Avec l'héritage * Plus de flexibilité, mais moins de sûreté * Contrôles de type effectués à l'exécution * Peut entraîner des ralentissements significatifs * Avec la généricité * Moins de flexibilité, mais plus de sûreté * Contrôles de type effectués à la compilation * Moins de ralentissement (voire aucun) à l'exécution Syntaxe * Mot-clé "template" * Suivi d'une liste de paramètres * Liste délimitée par "<" et ">" * Paramètres séparés par une virgule * Précède un composant générique * Fonction, classe ou méthode * Définit des paramètres * Soit des types: typename T * Soit des constantes: int N Fonctions génériques * Définition d'une fonction générique template <typename T> const T & min(const T & a,const T & b) { if (a < b) return a; return b; } * Appel à une fonction générique (instanciation) int i,j; ... int k = min<int>(i,j); * Instanciation ==> fixer les types paramétrés * Suppose l'opérateur "<" sur le type paramétré T * S'il n'existe pas ==> erreur de compilation * Possibilité de le définir ==> "surcharge" opérateur Polymorphisme statique * Il est possible d'omettre les types paramétrés à l'instanciation * Le compilateur peut déduire ces types * A condition qu'il dispose des informations nécessaires * Même mécanisme de déduction que la surcharge de nom * Il s'agit d'une forme de polymorphisme statique * Exemple * int i,j; ... min(i,j); ==> instanciation de " min<int>" * float a,b; ... min(a,b); ==> instanciation de " min<float>" * Le compilateur peut effectuer des conversions implicites si les types ne correspondent pas exactement Classes génériques * Définition d'une classe générique template <typename T,int N> class Pile { private: T elements[N]; int sommet; public: Pile(void); void ajouter(const T &); T retirer(void); }; * Instanciation d'une classe générique * Pile<int,256> p; STL: Standard Template Library * Bibliothèque standard du C++ basée sur les génériques * Fournit des conteneurs et des algorithmes génériques * Séquences élémentaires: vector, list, deque * Adaptations des séquences: stack, queue, priority_queue * Conteneurs associatifs: map, multimap, set, multiset * Algorithmes: find, sort, replace... * Normalisée en 1998 * Avant: STL = Standard Template Library * Après: Standard C++ Library |