本文學習內容參考:http://www.cnblogs.com/gw811/archive/2012/10/25/2738929.htmlhtml
C++模板ios
1.模板分爲函數模板和類模板兩種類型程序員
函數模板針對參數類型不一樣的函數;數組
類模板針對數據成員和成員函數類型不一樣的類;函數
使用模板的目的就是可以讓程序員編寫與類型無關的代碼。好比編寫了一個交換兩個整型int 類型的swap函數,這個函數就只能實現int 型,對double,字符這些類型沒法實現,要實現這些類型的交換就要從新編寫另外一個swap函數。使用模板的目的就是要讓這程序的實現與類型無關,好比一個swap模板函數,便可以實現int 型,又能夠實現double型的交換。學習
注意:模板的聲明或定義只能在全局,命名空間或類範圍內進行。即不能在局部範圍,函數內進行,好比不能在main函數中聲明或定義一個模板;spa
2.函數模板的通用格式以下:.net
template <class 形參名, class 形參名,......> 返回類型 函數名(參數列表) { 函數體 }
其中template 和 class 是關鍵字,這裏的class也能夠用 typename 關鍵字來代替。<>中的參數叫作模板形參,模板形參不能爲空。一旦聲明瞭模板函數,就能夠用模板函數的形參名聲明函數中的成員,即在該函數中使用內置類型的地方均可以使用模板形參名。模板函數在調用時,經過模板函數的實參來初始化模板形參,一旦編譯器肯定了實際的模板實參類型就稱他實例化了函數模板的一個實例。下面以swap的模板函數爲例:code
template <class T> void swap(T& a, T& b){};
當調用這樣的模板函數時,這裏的類型 T 就會被調用時的類型所替代。好比swap(a , b),當 a 和 b 是 int 時,模板函數swap中的形參 T 就會被 int 所替代,模板函數就變爲了swap(int& a, int& b)。而當swap(a , b)中的 a 和 b 爲 double 類型時,模板函數就相應地變爲了swap(double& a, double& b)。這樣也就實現了代碼與類型無關。htm
Demo: 求兩個數的最大值的模板函數
#include<iostream> using namespace std; template <typename T> const T& max(const T& a, const T& b) { return a > b ? a : b; } int main() { cout << max(2.1, 3.3) << endl; //模板實參被隱式推演爲double類型 cout << max<double>(2.1, 3.3) << endl; //顯示指定實參類型爲double cout << max<int>(2.1, 3.3) << endl; //顯示指定實參類型爲int system("pause"); return 0; }
result:
3.類模板的通用格式以下:
template <class 形參名, class 形參名......> class 類名 { .......... };
3.1類模板和函數模板都是以template開始後接模板形參列表組成,模板形參不能爲空,一但聲明瞭類模板就能夠用類模板的形參名聲明類中的成員變量和成員函數,便可以在類中使用內置類型的地方均可以使用模板形參名來聲明。
template <class T> class Demo { T a; public: Demo(T first); T GetValue(); };
3.2類模板的成員函數在類外面實現的定義方式以下(須要在每一個方法的實現前面添加 template<class T>):
template <class T> Demo<T>::Demo(T first){ a=first; } template <class T> T Demo<T>::GetValue(){ return a; }
4.模板特殊化(Template Specialization)(此處學習內容參考http://blog.csdn.net/fingding/article/details/32079289)
4.1模板的特殊化是當模板中的pattern有肯定的類型時,模板有一個具體的實現。例如假設咱們的類模板pair 包含一個取模計算(module operation)的函數,而咱們但願這個函數只有當對象中存儲的數據爲整型(int)的時候才能工做,其餘時候,咱們須要這個函數老是返回0。這能夠經過下面的代碼來實現:
#include<iostream> using namespace std; template<class T> class Pair { T value1; T value2; public: Pair(T first, T second) { value1 = first; value2 = second; } T Module() { return 0; } }; template<> class Pair<int> { int value1; int value2; public: Pair(int first, int second) { value1 = first; value2 = second; } int Module(); };
//template<> //此處正常狀況下須要,可是在VS2015中編譯的結果以下result11 int Pair<int>::Module() { return value1%value2; } int main() { Pair<int> p1(8, 3); Pair<float> p2(5.5, 2.3); cout << p1.Module() << endl; cout << p2.Module() << endl; system("pause"); return 0; }
result11:
1>------ 已啓動生成: 項目: Template specialization, 配置: Debug Win32 ------ 1> TemplateMain.cpp 1>c:\users\administrator\documents\visual studio 2015\projects\suanfa\shiyan1\test1--sequence\template specialization\templatemain.cpp(33): error C2910: 「Pair<int>::Module」: 沒法顯式專用化 1>c:\users\administrator\documents\visual studio 2015\projects\suanfa\shiyan1\test1--sequence\template specialization\templatemain.cpp(38): warning C4305: 「參數」: 從「double」到「float」截斷 ========== 生成: 成功 0 個,失敗 1 個,最新 0 個,跳過 0 個 ==========
以上的錯誤:error C2910 提示沒法顯示專用化,查詢C2910錯誤代碼,解決方案:去掉函數Module()實現時前面的 template<>便可;
能夠學習到不少關於生成與錯誤處理知識的連接:https://msdn.microsoft.com/zh-cn/library/z7kx322x.aspx
修改後的運行結果以下:
5.非類型形參示例(參考:http://www.cnblogs.com/gw811/archive/2012/10/25/2738929.html)
該示例實現的是讓用戶親自指定棧的大小,並實現棧的相關操做
TemplateDemo.h
#pragma once template <class T, int MAXSIZE>class Stack { //MAXSIZE由用戶建立對象時自行設定 private: T elements[MAXSIZE]; //包含棧中元素的數組 int numElements; //當前棧中元素的個數 public: Stack(); //構造函數 void push(T const&); //壓入元素 void pop(); //彈出元素 T top() const; //返回棧頂元素 bool Empty() const { //判斷棧是否爲空 return numElements == 0; } bool Full() const { //判斷棧棧是否已滿 return numElements == MAXSIZE; } }; template <class T,int MAXSIZE> Stack<T, MAXSIZE>::Stack() :numElements(0) { //初始時棧不含任何元素 } template <class T,int MAXSIZE> void Stack<T, MAXSIZE>::push(T const& elem) { if (numElements == MAXSIZE) { throw std::out_of_range("Stack<>::push():Stack if fulll"); } elements[numElements] = elem; //將新元素elem添加到棧中 ++numElements; //當前棧中元素個數加1 } template <class T,int MAXSIZE> void Stack<T, MAXSIZE>::pop() { if (numElements <= 0) { throw std::out_of_range("Stack<>::pop(),Stack is Empty"); } --numElements; //減小元素個數 } template <class T,int MAXSIZE> T Stack<T, MAXSIZE>::top() const{ if (numElements <= 0) { throw std::out_of_range("Stack<>::pop(),Stack is Empty"); } return elements[numElements - 1]; //返回最後(棧頂)一個元素 }
TemplateDemo.cpp
#include<iostream> #include<string> #include"TemplateDemo.h" using namespace std; int main() { try { Stack<int, 20> int20Stack; //能夠存儲20個int類型數據的棧 Stack<int, 40> int40Stack; //能夠存儲40個int類型數據的棧 Stack<string, 40> string40Stack; //能夠存儲40個string類型數據的棧 //使用存儲20個int類型數據的棧 int20Stack.push(7); cout << int20Stack.top() << endl; int20Stack.pop(); //使用可存儲40個string類型數據的棧 string40Stack.push("hello"); cout << string40Stack.top() << endl; string40Stack.pop(); string40Stack.pop(); system("pause"); return 0; } catch (const std::exception& ex) { cerr << "Exception: " << ex.what() << endl; system("pause"); return EXIT_FAILURE; //退出程序且有error標記 } }
result: