C++-Vorlage

黄舟
黄舟Original
2016-12-13 14:31:071367Durchsuche

Funktionsvorlage

Beim Einstieg in C++ werden viele Leute mit swap(int&, Der ähnliche Code für eine Funktion wie int&) lautet wie folgt:

void swap(int&a , int& b) {
    int temp = a;
    a =  b;
    b = temp;
}

Aber wenn Sie Long-, String- und benutzerdefinierte Klassenaustauschfunktionen unterstützen möchten, ähnelt der Code dem obigen Code, jedoch vom Typ Zu diesem Zeitpunkt definieren wir die Swap-Funktionsvorlage. Sie können verschiedene Arten von Swap-Funktionscodes wiederverwenden. Die Deklarationsform der Funktionsvorlage lautet wie folgt:

template <class identifier> function_declaration;
template <typename identifier> function_declaration;

Der Deklarations- und Definitionscode der Die Swap-Funktionsvorlage lautet wie folgt:

//method.h
template<typename T> void swap(T& t1, T& t2);

#include "method.cpp"
//method.cpp

template<typename  T> void swap(T& t1, T& t2) {
    T tmpT;
    tmpT = t1;
    t1 = t2;
    t2 = tmpT;
}

Das Obige ist die Deklaration und Definition der Vorlage. Die Instanziierung der Vorlage erfolgt durch den Compiler und hat nichts damit zu tun Wie verwende ich die obige Vorlage? . Dies unterscheidet sich von der allgemeinen Funktionsverwendung. Daher muss #include zur letzten Zeile der Datei method.h hinzugefügt werden „method.cpp“.

//main.cpp
#include <stdio.h>
#include "method.h"
int main() {
    //模板方法 
    int num1 = 1, num2 = 2;
    swap<int>(num1, num2);
    printf("num1:%d, num2:%d\n", num1, num2);  
    return 0;
}
Klassenvorlage

Stellen Sie sich vor, wir schreiben eine einfache Stapelklasse. Dieser Stapel kann den Typ int, den Typ long, den Typ string usw. unterstützen. Ohne Klassenvorlagen müssen wir drei Codes schreiben Die obige Stapelklasse ist im Grunde dieselbe. Über die Klassenvorlage können wir eine einfache Stapelvorlage definieren und sie dann je nach Bedarf als Int-Stack, Long-Stack oder String-Stack instanziieren.

Das Obige definiert eine Klassenvorlage – einen Stapel. Er dient nur zur Veranschaulichung der Verwendung der Klassenvorlage. Er kann nur bis zu 100 Elemente auf dem Stapel unterstützen . Das Verwendungsbeispiel lautet wie folgt:
//statck.h
template <class T> class Stack {
    public:
        Stack();
        ~Stack();
        void push(T t);
        T pop();
        bool isEmpty();
    private:
        T *m_pT;        
        int m_maxSize;
        int m_size;
};

#include "stack.cpp"
//stack.cpp
template <class  T>  Stack<T>::Stack(){
   m_maxSize = 100;      
   m_size = 0;
   m_pT = new T[m_maxSize];
}
template <class T>  Stack<T>::~Stack() {
   delete [] m_pT ;
}
        
template <class T> void Stack<T>::push(T t) {
    m_size++;
    m_pT[m_size - 1] = t;
    
}
template <class T> T Stack<T>::pop() {
    T t = m_pT[m_size - 1];
    m_size--;
    return t;
}
template <class T> bool Stack<T>::isEmpty() {
    return m_size == 0;
}

Vorlagenparameter

Eine Vorlage kann Typparameter, reguläre Typparameter int oder Standardvorlagenparameter wie
//main.cpp
#include <stdio.h>
#include "stack.h"
int main() {
    Stack<int> intStack;
    intStack.push(1);
    intStack.push(2);
    intStack.push(3);
    
    while (!intStack.isEmpty()) {
        printf("num:%d\n", intStack.pop());
    }
    return 0;
}


haben Die oben genannten Klassenvorlagen Der Stapel hat eine Einschränkung, das heißt, er kann nur maximal 100 Elemente unterstützen. Wir können Vorlagenparameter verwenden, um die maximale Anzahl von Elementen dieses Stapels zu konfigurieren . Der Code lautet wie folgt:

template<class T, T def_val> class Stack{...}

Verwendungsbeispiele sind wie folgt:
//statck.h
template <class T,int maxsize = 100> class Stack {
    public:
        Stack();
        ~Stack();
        void push(T t);
        T pop();
        bool isEmpty();
    private:
        T *m_pT;        
        int m_maxSize;
        int m_size;
};

#include "stack.cpp"
//stack.cpp
template <class T,int maxsize> Stack<T, maxsize>::Stack(){
   m_maxSize = maxsize;      
   m_size = 0;
   m_pT = new T[m_maxSize];
}
template <class T,int maxsize>  Stack<T, maxsize>::~Stack() {
   delete [] m_pT ;
}
        
template <class T,int maxsize> void Stack<T, maxsize>::push(T t) {
    m_size++;
    m_pT[m_size - 1] = t;
    
}
template <class T,int maxsize> T Stack<T, maxsize>::pop() {
    T t = m_pT[m_size - 1];
    m_size--;
    return t;
}
template <class T,int maxsize> bool Stack<T, maxsize>::isEmpty() {
    return m_size == 0;
}

Vorlagenspezialisierung

//main.cpp
#include <stdio.h>
#include "stack.h"
int main() {
    int maxsize = 1024;
    Stack<int,1024> intStack;
    for (int i = 0; i < maxsize; i++) {
        intStack.push(i);
    }
    while (!intStack.isEmpty()) {
        printf("num:%d\n", intStack.pop());
    }
    return 0;
}
Wenn wir verschiedene Implementierungen von definieren möchten Als Vorlage können wir die Vorlagenspezialisierung verwenden. Wenn es sich beispielsweise bei der von uns definierten Stapelklassenvorlage um einen Stapel vom Typ char* handelt, hoffen wir, alle Daten von char in die Stapelklasse zu kopieren, da nur der char-Zeiger gespeichert wird und der Speicher, auf den der char-Zeiger zeigt kann ungültig werden und das vom Stapel angezeigte Stapelelement Der Speicher, auf den der char-Zeiger zeigt, ist möglicherweise ungültig. Es gibt auch die von uns definierte Auslagerungsfunktionsvorlage. Wenn das vom Container gespeicherte Objekt groß ist, belegt es viel Speicher und verringert die Leistung, da ein temporäres großes Objekt generiert werden muss Um ein Problem zu lösen, ist eine Spezialisierung erforderlich.

Spezialisierung von Funktionsvorlagen

Angenommen, unsere Swap-Funktion möchte eine Situation bewältigen. Wir haben zwei Vektorenbd43222e33876353aff11e13a7dc75f6 und führen tmpT = aus t1 muss alle Elemente von t1 kopieren, was viel Speicher beansprucht und zu Leistungseinbußen führt. Daher löst unser System dieses Problem durch die Funktion vector.swap. Der Code lautet wie folgt:

templatea8093152e673feb7aba1828c43532094 Präfix bedeutet, dass es sich um eine Spezialisierung handelt, für deren Beschreibung keine Vorlagenparameter erforderlich sind. Das Verwendungsbeispiel lautet wie folgt:
//method.h
template<class T> void swap(T& t1, T& t2);

#include "method.cpp"
#include <vector>
using namespace std;
template<class T> void swap(T& t1, T& t2) {
    T tmpT;
    tmpT = t1;
    t1 = t2;
    t2 = tmpT;
}

template<> void swap(std::vector<int>& t1, std::vector<int>& t2) {
    t1.swap(t2);
}

vectorbd43222e33876353aff11e13a7dc75f6 begrenzt. Wenn Sie die Vorlagenspezialisierung verwenden möchten, um den Austausch aller Vektoren zu lösen, müssen Sie nur den folgenden Code

//main.cpp
#include <stdio.h>
#include <vector>
#include <string>
#include "method.h"
int main() {
    using namespace std;
    //模板方法 
    string str1 = "1", str2 = "2";
    swap(str1, str2);
    printf("str1:%s, str2:%s\n", str1.c_str(), str2.c_str());  
    
    vector<int> v1, v2;
    v1.push_back(1);
    v2.push_back(2);
    swap(v1, v2);
    for (int i = 0; i < v1.size(); i++) {
        printf("v1[%d]:%d\n", i, v1[i]);
    }
    for (int i = 0; i < v2.size(); i++) {
        printf("v2[%d]:%d\n", i, v2[i]);
    }
    return 0;
}

in

template<> void swap(std::vector<int>& t1, std::vector<int>& t2) {
    t1.swap(t2);
}

Die anderen Codes bleiben unverändert.

Klassenvorlagenspezialisierung
template<class V> void swap(std::vector<V>& t1, std::vector<V>& t2) {
    t1.swap(t2);
}

Bitte sehen Sie sich den Vergleichscode unten an:

Beim Vergleich zweier Ganzzahlen ist die Gleichheitsmethode des Vergleichs korrekt, aber vergleichen Sie Wann Der Vorlagenparameter ist char*, die Vorlage funktioniert nicht, daher ist die Änderung wie folgt:

//compare.h
template <class T>
 class compare
 {
  public:
  bool equal(T t1, T t2)
  {
       return t1 == t2;
  }
};
#include <iostream>
#include "compare.h"
 int main()
 {
  using namespace std;
  char str1[] = "Hello";
  char str2[] = "Hello";
  compare<int> c1;
  compare<char *> c2;   
  cout << c1.equal(1, 1) << endl;        //比较两个int类型的参数
  cout << c2.equal(str1, str2) << endl;   //比较两个char *类型的参数
  return 0;
 }
Die Datei main.cpp bleibt unverändert und dieser Code kann normal funktionieren.

Vorlagentypkonvertierung
//compare.h
#include <string.h>
template <class T>
 class compare
 {
  public:
  bool equal(T t1, T t2)
  {
       return t1 == t2;
  }
};
   

template<>class compare<char *>  
{
public:
    bool equal(char* t1, char* t2)
    {
        return strcmp(t1, t2) == 0;
    }
};

Erinnern Sie sich noch an unsere angepasste Stack-Vorlage? In unserem Programm lautet der Code wie folgt:

//shape.h
class Shape {

};
class Circle : public Shape {
};
Dann hoffen wir, es so zu verwenden:


Dies kann nicht kompiliert werden, da Stackbc7f3882d55c1dbc40436bcd5b582091 nicht die übergeordnete Klasse von Stackd89ac632506285f7027c2757056343b9 , aber wir möchten, dass der Code so funktioniert, dann müssen wir den Stack-Code wie folgt definieren:

//main.cpp
#include <stdio.h>
#include "stack.h"
#include "shape.h"
int main() {
    Stack<Circle*> pcircleStack;
    Stack<Shape*> pshapeStack;
    pcircleStack.push(new Circle);
    pshapeStack = pcircleStack;
    return 0;
}

Auf diese Weise ist Stack< ;Circle> oder Stack751c65e59cbb165c6b0fb9c66278663c kann automatisch in Stackbc7f3882d55c1dbc40436bcd5b582091 konvertiert werden.
//statck.h
template <class T> class Stack {
    public:
        Stack();
        ~Stack();
        void push(T t);
        T pop();
        bool isEmpty();
        template<class T2>  operator Stack<T2>();
    private:
        T *m_pT;        
        int m_maxSize;
        int m_size;
};

#include "stack.cpp"
template <class  T>  Stack<T>::Stack(){
   m_maxSize = 100;      
   m_size = 0;
   m_pT = new T[m_maxSize];
}
template <class T>  Stack<T>::~Stack() {
   delete [] m_pT ;
}
        
template <class T> void Stack<T>::push(T t) {
    m_size++;
    m_pT[m_size - 1] = t;
    
}
template <class T> T Stack<T>::pop() {
    T t = m_pT[m_size - 1];
    m_size--;
    return t;
}
template <class T> bool Stack<T>::isEmpty() {
    return m_size == 0;
}

template <class T> template <class T2>  Stack<T>::operator Stack<T2>() {
    Stack<T2> StackT2;
    for (int i = 0; i < m_size; i++) {
        StackT2.push((T2)m_pT[m_size - 1]);
    }
    return StackT2;
}
Andere
//main.cpp
#include <stdio.h>
#include "stack.h"
#include "shape.h"
int main() {
    Stack<Circle*> pcircleStack;
    Stack<Shape*> pshapeStack;
    pcircleStack.push(new Circle);
    pshapeStack = pcircleStack;
    return 0;
}

Eine Klasse hat keine Vorlagenparameter, aber die Mitgliedsfunktion hat Vorlagenparameter. Der Code lautet wie folgt:

Sie können sogar Wenn Sie Util gleich als statisch deklarieren, lautet der Code wie folgt:

class Util {
    public:
        template <class T> bool equal(T t1, T t2) {
            return t1 == t2;
        }
};

int main() {
    Util util;
    int a = 1, b = 2;
    util.equal<int>(1, 2);
    return 0;
}

Stellungnahme:
Der Inhalt dieses Artikels wird freiwillig von Internetnutzern beigesteuert und das Urheberrecht liegt beim ursprünglichen Autor. Diese Website übernimmt keine entsprechende rechtliche Verantwortung. Wenn Sie Inhalte finden, bei denen der Verdacht eines Plagiats oder einer Rechtsverletzung besteht, wenden Sie sich bitte an admin@php.cn
Vorheriger Artikel:Virtuelle C#-FunktionNächster Artikel:Virtuelle C#-Funktion