C++ 泛型编程(一):模板基础:函数模板,类模板,模板原理,模板匹配规则
-
類模板
-
函數模板
泛型編程
泛型編程,泛型即是指具有在多種數據類型上皆可操作的含義,其實就是能夠幫助開發者編寫完全一般化并可重復使用的算法,同樣的工作不需要做多次,同樣的算法針對不同的類型也不應該寫多次,所以需要通過某種途徑,來使一個容器或者算法,能夠兼容所有的類型,這就是泛型編程。
void Swap(int& left, int& right) {int temp = left;left = right;right = temp; } void Swap(double& left, double& right) {double temp = left;left = right;right = temp; } void Swap(char& left, char& right) {char temp = left;left = right;right = temp; }就比如非常常用的swap函數,雖然c++支持重載,但是如果對于這種函數我們每一個都要自己去實現,是一件很麻煩并且多余的工作,因為我們將重復邏輯的東西多次實現。
class Stack {private:int capacity;int size;int* arr; };又比如一個數據結構,如果我們實現了一個棧,如果他此時要存儲其他的數據類型,那我們就必須還要重新修改一個,這無疑是多余的。
所以,c++基于重載這一項機制,實現了模板編程,模板作為類或者函數的藍圖,可以針對不同類型,來實現對應操作。
函數模板
函數模板
該函數模板與類型無關,在使用時被參數化,根據實參類型產生函數的特定
類型版本。
用法
template<typename T1, typename T2,......,typename Tn> //typename即類型名,也可以用class替代,這里的class指的是類型,不能用struct替換只需要在對應的函數前面加上這一句即可,然后將所有需要替換類型的參數改為上面的T1,T2即可
template<class T> void Swap(T& left, T& right) {T temp = left;left = right;right = temp; }int main() {int i = 3, j = 4;double a = 3.4, b = 5.6;char x = 'x', y = 'y';Swap(i, j);Swap(a, b);Swap(x, y);cout << i << ' ' << j << endl;cout << a << ' ' << b << endl;cout << x << ' ' << y << endl; }
可以看到,這樣就可以適用于多重類型。
函數模板的原理
下面來討論一下,當我們調用這個模板函數的時候,是通過這個模板函數來實現對應的功能?還是它可能會重載成其他函數,再調用其他的函數呢?
這是只需要看看匯編代碼就可以了
可以看到,它調用的是三個不同的函數,這時候就可以推論出來。
模板函數本身并不是一個函數,而是一個藍圖,通過識別我們傳入的參數,然后在底層生成一個該類型的模板函數,并調用該函數。并且這個模板只在第一次使用的時候才會實例化出來
并且這個階段是在預處理的時候就進行了,因為我們仔細思考一下,如果它是在編譯階段才進行函數的生成,那肯定是無法通過語法的檢查的,所以這一階段只能在預處理進行。
函數模板的實例化
模板的實例化有兩種方法,一種是顯式實例化,一種是隱式實例化
隱式實例化
template<class T> T Add(const T& left, const T& right) {return left + right; }int main() {int i = 3, j = 4;double a = 3.4, b = 5.6;Add(i, j);Add(a, b);/*這時編譯器就會報錯,因為需要通過參數推演出對應類型,但是此時就無法推演出到底是將T推演成double還是將T推演成intAdd(i, a);*/// 此時有兩種處理方式:1. 用戶自己來強制轉化 2. 使用顯式實例化Add(i, (int)a);return 0; }顯式實例化
int main() {int i = 3;double x = 3.4;// 顯式實例化Add<int>(i, x);return 0; }這種則是用尖括號來顯式的聲明,STL中的容器等就是采用這種顯式的實例化來明確參數的類型。
函數模板的匹配規則(引用)
類模板
用法
類模板的用法和函數模板其實一樣
template<class T> class Stack {private:int capacity;int size;T* arr; };這里的Stack不是一個具體的類,他是類模板,也就是一個藍圖,通過這個模板來識別參數的類型并生成對應的模板類。所以可以理解為類模板是一個類家族,模板類是通過類模板實例化的具體類
如果類中的成員函數需要在類外定義的話,需要每一個函數前都要聲明一次類模板的參數列表
template<class T> class Stack { public:void push();void pop(); private:int capacity;int size;T* arr; };template<class T> void Stack<T>::push() {}template<class T> void Stack<T>::pop() {}還有一個需要注意的地方就是,類模板的所有成員函數都是模板函數
類模板的實例化
類模板只能夠通過顯式實例化
如STL中的幾個容器都是通過類模板實現的
stack<int>并不是類名,而是類型,stack才是類名
總結
以上是生活随笔為你收集整理的C++ 泛型编程(一):模板基础:函数模板,类模板,模板原理,模板匹配规则的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: C++ 如何一次在堆上申请4G的内存?如
- 下一篇: C++ STL : 模拟实现STL中的s