Date de première publication : 2013/10/16
Dans ce TP, nous allons nous intéresser à la généricité et voir son application pratique pour les fonctions (enfin, une) puis pour les classes (deux ...).
Fonctions paramétrées
Il faut reprendre la fonction max()
vue en cours :
const int& max(const int& a,const int & b) {
return ((a > b) ? a : b);
}
- Écrire la fonction
max
template (euh, appelez la plutôt maximum ...) - Instancier la fonction avec deux variables de même type
- Instancier la fonction avec deux variables de types différents
- Instancier la fonction avec deux variables de types différents mais en forçant le type pour éviter le message d'erreur
Classes paramétrées
Conversion presque automatique
Vous devez transformer le vecteur dynamique de nombres réels et la pile d'entiers codés aux TPs précédents en classes paramétrées.
Utilisez le petit algorithme vu en cours :
- Choisir une classe non paramétrée écrite correctement et dont le fonctionnement est éprouvé (par des tests unitaires par exemple)
- Créer un nouveau fichier, bien mettre à jour les gardiens
- Recopier la déclaration et la définition de la classe non paramétrée dans ce fichier
- Paramétrer la classe, les méthodes, ...
- Reprendre le code de test de la classe non paramétrée, le mettre à jour en instanciant le template
- Vérifier que tout va bien (en relançant les tests unitaires)
- Recommencer au 1 tant qu'il reste une classe à paramétrer :-)
Pour le fun, vous pouvez bien entendu instancier vos classes avec d'autres types que double
et int
.
- Un template est un modèle qui n'est jamais compilé (seules les instanciations le sont)
- Un template doit être instancié pour que le compilateur daigne s'y intéresser [corollaire]
Avec de l'expérience, on pense plus facilement directement à la version générique.
Si vous avez fait l'effort d'utiliser les jeux de tests, ceux-ci sont faciles à réutiliser avec un typedef
ou un using
.
// typedef PileGen<int> Pile; // ça marche mais c'est un peu old school
using Pile = PileGen<int>;
TEST_CASE("Constructeur par defaut") {
Pile p;
CHECK( p.empty() );
CHECK( 0 == p.size() );
}
Fonction amie template
Les fonctions amies templates sont très sympathiques à écrire suivant qu'elles sont définies dans la classe elle-même ou en dehors...
En version en ligne :
template <typename T>
class VecteurGen {
friend VecteurGen operator+(const VecteurGen &a, const VecteurGen& b) {
return ...;
}
};
En version déportée :
template <typename T>
class VecteurGen {
template <typename U> friend VecteurGen<U> operator+(const VecteurGen<U> &, const VecteurGen<U>&) ;
};
template <typename T>
VecteurGen<T> operator+(const VecteurGen<T> & a, const VecteurGen<T> & b) {
}
Encore un peu ?
Vous voulez faire encore une autre structure de données, une liste chaînée par exemple, c'est par là... Dans cet exercice, on code la notion d'itérateurs et la surcharge des operator++()
.
Fil rouge ...
Pour cette partie de fil rouge, on se propose de créer une méthode clone()
ou copie()
qui permet d'obtenir une copie de l'objet courant. La méthode doit être déclarée comme virtuelle constante dans la classe Forme
et renvoyer un Forme *
Grâce à ce que l'on appelle le type de retour covariant, les redéfinitions dans les classes filles peuvent renvoyer un pointeur sur un objet de classe fille et non un pointeur sur un objet de classe mère.
La méthode clone()
vous donnera un peu de travail pour la classe Groupe
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10