C ++ - Vorlagen

Vorlagen bilden die Grundlage für die generische Programmierung, bei der Code unabhängig von einem bestimmten Typ geschrieben wird.

Eine Vorlage ist eine Blaupause oder Formel zum Erstellen einer generischen Klasse oder Funktion. Die Bibliothekscontainer wie Iteratoren und Algorithmen sind Beispiele für generische Programmierung und wurden unter Verwendung des Vorlagenkonzepts entwickelt.

Für jeden Container gibt es eine einzige Definition, z vector, aber wir können zum Beispiel viele verschiedene Arten von Vektoren definieren, vector <int> oder vector <string>.

Sie können Vorlagen verwenden, um Funktionen und Klassen zu definieren. Lassen Sie uns sehen, wie sie funktionieren.

Funktionsvorlage

Die allgemeine Form einer Vorlagenfunktionsdefinition wird hier gezeigt -

template <class type> ret-type func-name(parameter list) {
   // body of function
}

Hier ist type ein Platzhaltername für einen Datentyp, der von der Funktion verwendet wird. Dieser Name kann innerhalb der Funktionsdefinition verwendet werden.

Das folgende Beispiel zeigt eine Funktionsvorlage, die maximal zwei Werte zurückgibt:

#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;
}

Wenn wir den obigen Code kompilieren und ausführen, würde dies das folgende Ergebnis erzeugen:

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

Klassenvorlage

So wie wir Funktionsvorlagen definieren können, können wir auch Klassenvorlagen definieren. Die allgemeine Form einer generischen Klassendeklaration wird hier gezeigt -

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

Hier, typeist der Name des Platzhaltertyps, der angegeben wird, wenn eine Klasse instanziiert wird. Sie können mehr als einen generischen Datentyp definieren, indem Sie eine durch Kommas getrennte Liste verwenden.

Das folgende Beispiel definiert die Klasse Stack <> und implementiert generische Methoden, um die Elemente vom Stapel zu verschieben und zu entfernen.

#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;
   } 
}

Wenn wir den obigen Code kompilieren und ausführen, würde dies das folgende Ergebnis erzeugen:

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