C++ Modèles

Les modèles sont la base de la programmation générique, qui est une manière d'écrire du code indépendant de tout type spécifique.

Un modèle est un plan ou une formule pour créer des classes ou des fonctions génériques. Les conteneurs de bibliothèque, tels que les itérateurs et les algorithmes, sont des exemples de programmation générique, et ils utilisent tous le concept de modèles.

Chaque conteneur a une définition unique, commevectorNous pouvons définir de nombreux types différents de vecteurs, commevector <int>ouvector <string>。

Vous pouvez utiliser des modèles pour définir des fonctions et des classes. Voyons comment les utiliser.

modèle de fonction

La forme générale d'une définition de modèle de fonction est la suivante :

template <typename type> ret-type func-name(parameter list) { // corps de la fonction }

Ici, type est un nom de substitution pour le type de données utilisé par la fonction. Ce nom peut être utilisé dans la définition de la fonction.

Voici un exemple de modèle de fonction qui retourne le maximum de deux nombres :

Exemple

#include <iostream> #include <string> using namespace std; template <typename T> inline T const& Max (T const& a, T const& b) { return a < b ? b:a; } int main () { int i = 39; int j = 20; cout << "Max(i, j): " << Max(i, j) << endl; double f1 = 13.5; double f2 = 20.7; cout << "Max(f1, f2): " << Max(f1, f2) << endl; string s1 = "Hello"; string s2 = "World"; cout << "Max(s1, s2): " << Max(s1, s2) << endl; return 0; }

Lorsque le code ci-dessus est compilé et exécuté, il produit les résultats suivants :

Max(i, j): 39
Max(f1, f2): 20.7
Max(s1, s2): World

modèle de classe

Tout comme nous définissons des modèles de fonctions, nous pouvons également définir des modèles de classes. La forme générale d'une déclaration de classe générique est la suivante :

template <class type> class class-name {
.
.
.
}

Ici,typeIl s'agit d'un nom de type de remplacement qui peut être spécifié lors de l'instanciation de la classe. Vous pouvez utiliser une liste séparée par des virgules pour définir plusieurs types de données génériques.

L'exemple suivant définit la classe Stack<> et implémente des méthodes génériques pour empiler et dépiler des éléments :

Exemple

#include <iostream> #include <vector> #include <cstdlib> #include <string> #include <stdexcept> using namespace std; template <class T> class Stack { private: vector<T> elems; // élément public: void push(T const&); // Empiler void pop(); // Dépiler T top() const; // renvoie l'élément au sommet de la pile bool empty() const{ // renvoie true si vide. return elems.empty(); } }; template <class T> void Stack<T>::push (T const& elem) { // ajoute une copie de l'élément passé elems.push_back(elem); } template <class T> void Stack<T>::pop () { if (elems.empty()) { throw out_of_range("Stack<>::pop(): pile vide"); } // Supprime le dernier élément elems.pop_back(); } template <class T> T Stack<T>::top () const { if (elems.empty()) { throw out_of_range("Stack<>::top(): pile vide"); } // renvoie une copie du dernier élément return elems.back(); } int main() { try { Stack<int> intStack; // pile de type int Stack<string> stringStack; // pile de type string // opérer sur la pile int intStack.push(7); cout << intStack.top() <<endl; // opérer sur la pile string stringStack.push("hello"); cout << stringStack.top() << std::endl; stringStack.pop(); stringStack.pop(); } catch (exception const& ex) { cerr << "Exception: " << ex.what() <<endl; return -1; } }

Lorsque le code ci-dessus est compilé et exécuté, il produit les résultats suivants :

7
hello
Exception: Stack<>::pop(): empty stack
autres extensions