Menu
Coddy logo textTech

Templates de classes

Fait partie de la section Programmation Orientée Objet du Journey C++ de Coddy. Leçon 65 sur 104.

Tout comme les modèles de fonctions vous permettent d'écrire des fonctions indépendantes du type, les modèles de classes vous permettent de créer des classes indépendantes du type. C'est ainsi que fonctionnent les conteneurs comme std::vector : vous définissez la structure une seule fois, et le compilateur génère des versions spécifiques pour chaque type que vous utilisez.

template <typename T>
class Box {
    T value;
public:
    Box(T v) : value(v) {}
    T getValue() const { return value; }
    void setValue(T v) { value = v; }
};

int main() {
    Box<int> intBox(42);
    Box<std::string> strBox("Hello");
    
    std::cout << intBox.getValue() << std::endl;  // 42
    std::cout << strBox.getValue() << std::endl;  // Hello
}

Contrairement aux templates de fonctions, vous devez spécifier explicitement le type lors de la création d'objets à partir de templates de classes en utilisant des chevrons. Le compilateur génère ensuite une définition de classe complète pour ce type spécifique.

Les templates de classe peuvent avoir plusieurs paramètres de type et même des paramètres non-type comme des entiers :

template <typename T, int Size>
class FixedArray {
    T data[Size];
public:
    T& operator[](int index) { return data[index]; }
    int size() const { return Size; }
};

FixedArray<double, 5> arr;  // Tableau de 5 doubles
arr[0] = 3.14;

Lorsque vous définissez des fonctions membres en dehors de la classe, vous devez répéter la déclaration du modèle :

template <typename T>
class Container {
    T* data;
public:
    Container();
    ~Container();
};

template <typename T>
Container<T>::Container() : data(nullptr) {}

template <typename T>
Container<T>::~Container() { delete data; }

Les templates de classe constituent le fondement de la programmation générique en C++, vous permettant d'écrire des structures de données réutilisables qui fonctionnent avec n'importe quel type.

challenge icon

Défi

Facile

Construisons un système de stockage générique à l'aide de modèles de classes afin de créer un conteneur flexible capable de contenir n'importe quel type de données. Vous organiserez votre classe modèle dans un fichier d'en-tête et démontrerez sa polyvalence avec différents types dans votre programme principal.

Vous créerez deux fichiers :

  • Storage.h : définissez un modèle de classe appelé Storage qui agit comme un conteneur simple pour une seule valeur, avec quelques opérations utiles :

    Votre modèle Storage doit comporter :

    • Un membre privé pour contenir la valeur stockée
    • Un constructeur qui prend une valeur initiale
    • Une méthode getValue() qui renvoie la valeur stockée
    • Une méthode setValue() qui met à jour la valeur stockée
    • Une méthode isEmpty() qui renvoie true si la valeur est égale à la valeur construite par défaut du type T, et false dans le cas contraire

    Créez également un modèle de classe appelé Pair avec deux paramètres de type, qui stocke deux valeurs associées :

    • Des membres privés pour la première et la deuxième valeur (de types potentiellement différents)
    • Un constructeur qui initialise les deux valeurs
    • Des méthodes getFirst() et getSecond() pour récupérer chaque valeur
    • Une méthode display() qui affiche : (<first>, <second>)
  • main.cpp : lisez quatre entrées (chacune sur une ligne distincte) :
    1. Une valeur entière
    2. Une nouvelle valeur entière
    3. Une valeur de type chaîne de caractères
    4. Une valeur de type double

    Démontrez vos modèles en :

    1. Créant un Storage<int> avec le premier entier, puis en affichant : Int storage: <value>
    2. Le mettant à jour avec le deuxième entier à l'aide de setValue(), puis en affichant : Updated: <value>
    3. Créant un Storage<std::string> avec la chaîne saisie, puis en affichant : String storage: <value>
    4. Vérifiant si le stockage de la chaîne est vide et en affichant : Is empty: <true/false> (affichez true ou false)
    5. Créant un Pair<std::string, double> avec la chaîne et la valeur double, puis en appelant display()
    6. Créant un Pair<int, int> avec les deux valeurs entières, puis en appelant display()

Par exemple, avec les entrées 42, 100, Hello et 3.14 :

Int storage: 42
Updated: 100
String storage: Hello
Is empty: false
(Hello, 3.14)
(42, 100)

Remarquez comment le même modèle Storage fonctionne parfaitement avec les entiers et les chaînes, et comment Pair peut combiner différents types. Le compilateur génère des définitions de classes distinctes pour chaque combinaison de types que vous utilisez. N'oubliez pas d'utiliser la syntaxe template <typename T> pour les modèles à type unique et template <typename T, typename U> pour les modèles comportant plusieurs paramètres de type.

Essayez vous-même

#include <iostream>
#include <string>
#include "Storage.h"

using namespace std;

int main() {
    // Lire les entrées
    int intValue1;
    int intValue2;
    string strValue;
    double doubleValue;
    
    cin >> intValue1;
    cin >> intValue2;
    cin >> strValue;
    cin >> doubleValue;
    
    // TODO: Créer Storage<int> avec le premier entier et afficher : Int storage: <value>
    
    // TODO: Mettre à jour avec le deuxième entier en utilisant setValue(), afficher : Updated: <value>
    
    // TODO: Créer Storage<std::string> avec l'entrée de chaîne, afficher : String storage: <value>
    
    // TODO: Vérifier si le stockage de chaîne est vide, afficher : Is empty: true/false
    
    // TODO: Créer Pair<std::string, double> avec la chaîne et le double, appeler display()
    
    // TODO: Créer Pair<int, int> avec les deux entiers, appeler display()
    
    return 0;
}
quiz iconTestez-vous

Cette leçon comprend un petit quiz. Commencez la leçon pour y répondre et suivre votre progression.

Toutes les leçons de Programmation Orientée Objet

Entraînez-vous par vous-même : Compilateur C++ en ligne