1、template的使用
C++ 的高級玩法,當然包含了模板。模板(template)是實現代碼重用機制的一種工具,它可以實現類型參數化,把類型定義爲參數(模板元編程),從而實現了真正的代碼可重用性。
模板是用來批量生成功能和形式都幾乎相同的代碼的。編譯器就能在需要的時候,根據模板自動生成程序的代碼。從同一個模板自動生成的代碼,形式幾乎是一樣的。 模板就像一個做餅乾的模具,至於餅乾是什麼味道,則要看具體實例化時製作餅乾的材料。
模板可以分爲兩類,一個是函數模板,另外一個是類模板。
1.1、函數模板
函數模板比較簡單,下面我們來看一個兩者交換的例子就明白了:
template<typename T>
void swap(T& t1, T& t2)
{
T temp = t2;
t2 = t1;
t1 = temp;
}
1.2、類模板
類模板比函數模板稍微複雜一下,主要是實現時的書寫,如下面的代碼:
//stack.h
template<typename T>
class Stack
{
public:
Stack();
~Stack();
void push(T t);
T pop();
bool isEmpty();
private:
T* m_pT;
int m_maxSize;
int m_size;
};
//Stack.cpp
#include "Stack.h"
template<typename T>
Stack<T>::Stack()
{
m_maxSize = 100;
m_size = 0;
m_pT = new T[m_maxSize];
}
template<typename T>
Stack<T>::~Stack()
{
delete[] m_pT;
m_pT = nullptr;
}
template<typename T>
void Stack<T>::push(T t)
{
m_size++;
m_pT[m_size - 1] = t;
}
template<typename T>
T Stack<T>::pop()
{
T t = m_pT[m_size - 1];
m_size--;
return t;
}
template<typename T>
bool Stack<T>::isEmpty()
{
return m_size == 0;
}
上述類模板是模仿了一個棧,這個棧很簡單,最多隻能支持100個元素入棧。
通過上面的例子可知,在類模板中,通用類型可以作爲普通成員變量,也可以作爲成員函數的參數和返回值。
2、模板的實例化與具象化
2.1、實例化
模板的實例化有兩種形式,分別是 顯示實例化 和 隱式實例化。
顯示實例化 就是直接命令編譯器創建特定的實例。在使用模板之前,編譯器會根據顯示指定的類型生成模板實例。顯示實例化有兩種寫法,具體如下:
template void swap2<int>(int& a, int& b); //聲明時顯示實例化,只需要聲明,不需要實現
int a = 1, b= 2;
swap<int>(a, b); //使用時顯示實例化
隱式實例化 類似普通的函數調用,在使用模板時,根據使用的類型,編譯器進行推導,生成相應類型的實例。方便程序員的書寫,但是增加編譯器的負擔。如下所示:
swap(a, b); //隱式實例化,和顯示實例化的結果是一樣的
2.2、具象化(專業化)
具象化就是模板中特化性質。例如上面書寫的交換函數,如果傳入的是char* 類型,使用 = 操作只是複製了指針數據,指針指向的內存有可能會失效,所以 = 操作可能會出現問題,我們需要進行單獨的操作。如下:
template<>
void swap2(char*& a, char*& b)
{
//具象化
.....
}
具象化的定義應該在有常規模板的情況下,以 template<> 打頭,通過名稱來指出類型,並必須要有具體的實現。
函數在調用的過程時,編譯器調用順序是:常規函數 > 具體化模板函數 > 常規模板。
3、其它
一個類沒有模板參數,但是成員函數有模板參數是可行的。代碼如下:
class Util
{
public:
template<class T>
bool equal(T t1, T t2)
{
return t1 == t2;
}
};
int main()
{
Util aab;
std::cout << aab.equal<int>(a, b) << std::endl;
std::cout << aab.equal(1, 1) << std::endl;
}
在類模板的例子中棧的最大元素數量是寫死的,可以使用模板的偏特化特性來自定義元素的最大數量。如下所示
template<typename T, int maxsize = 100>
class Stack
{
//和上面的例子一樣
.....
}
template <class T,int maxsize> //這裏和上面的不一樣
Stack<T, maxsize>::Stack()
{
m_maxSize = maxsize; //最大數量通過外面傳入
m_size = 0;
m_pT = new T[m_maxSize];
}
int main()
{
int maxsize = 1024;
Stack<int,1024> intStack;
for (int i = 0; i < maxsize; i++)
intStack.push(i);
}
感謝大家,我是假裝很努力的YoungYangD(小羊)。
參考文檔:
https://www.cnblogs.com/yangxiaoping/p/8268209.html
https://blog.csdn.net/qq_30835655/article/details/76850894