Modèles C ++
Les modèles sont à la base de la programmation générique, qui implique l'écriture de code d'une manière indépendante de tout type particulier.
Un modèle est un plan ou une formule pour créer une classe générique ou une fonction. Les conteneurs de bibliothèque comme les itérateurs et les algorithmes sont des exemples de programmation générique et ont été développés en utilisant le concept de modèle.
Il existe une seule définition de chaque conteneur, telle que vector, mais nous pouvons définir de nombreux types de vecteurs différents, par exemple, vector <int> ou vector <string>.
Vous pouvez utiliser des modèles pour définir des fonctions ainsi que des classes, voyons comment ils fonctionnent -
Modèle de fonction
La forme générale d'une définition de fonction de modèle est affichée ici -
template <class type> ret-type func-name(parameter list) {
// body of function
}
Ici, type est un nom d'espace réservé pour un type de données utilisé par la fonction. Ce nom peut être utilisé dans la définition de fonction.
Voici l'exemple d'un modèle de fonction qui renvoie le maximum de deux valeurs -
#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;
}
Si nous compilons et exécutons le code ci-dessus, cela produirait le résultat suivant -
Max(i, j): 39
Max(f1, f2): 20.7
Max(s1, s2): World
Modèle de classe
Tout comme nous pouvons définir 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 présentée ici -
template <class type> class class-name {
.
.
.
}
Ici, typeest le nom du type d'espace réservé, qui sera spécifié lorsqu'une classe est instanciée. Vous pouvez définir plusieurs types de données génériques à l'aide d'une liste séparée par des virgules.
Voici l'exemple pour définir la classe Stack <> et implémenter des méthodes génériques pour pousser et faire apparaître les éléments de la pile -
#include <iostream>
#include <vector>
#include <cstdlib>
#include <string>
#include <stdexcept>
using namespace std;
template <class T>
class Stack {
private:
vector<T> elems; // elements
public:
void push(T const&); // push element
void pop(); // pop element
T top() const; // return top element
bool empty() const { // return true if empty.
return elems.empty();
}
};
template <class T>
void Stack<T>::push (T const& elem) {
// append copy of passed element
elems.push_back(elem);
}
template <class T>
void Stack<T>::pop () {
if (elems.empty()) {
throw out_of_range("Stack<>::pop(): empty stack");
}
// remove last element
elems.pop_back();
}
template <class T>
T Stack<T>::top () const {
if (elems.empty()) {
throw out_of_range("Stack<>::top(): empty stack");
}
// return copy of last element
return elems.back();
}
int main() {
try {
Stack<int> intStack; // stack of ints
Stack<string> stringStack; // stack of strings
// manipulate int stack
intStack.push(7);
cout << intStack.top() <<endl;
// manipulate string stack
stringStack.push("hello");
cout << stringStack.top() << std::endl;
stringStack.pop();
stringStack.pop();
} catch (exception const& ex) {
cerr << "Exception: " << ex.what() <<endl;
return -1;
}
}
Si nous compilons et exécutons le code ci-dessus, cela produirait le résultat suivant -
7
hello
Exception: Stack<>::pop(): empty stack