標籤:概念 重載 技術分享 span 編譯器 width 功能 stream pre
泛型語義
泛型(Generic Programming),即是指具有在多種資料類型上皆可操作的含意。泛型編
程的代表作品 STL 是一種高效、泛型、可互動操作的軟體組件。
泛型程式設計最初誕生於 C++中,目的是為了實現 C++的 STL(標準模板庫)。其語言支
持機制就是模板(Templates)。
模板的精神其實很簡單:型別參數化(type parameterized),即,類型也是一種參數,
也是一種靜多態。 換句話說, 把一個原本特定於某個類型的演算法或類當中的類型資訊抽掉,
抽出來做成模板參數。
函數模板
引子:重載函數,雖然在一定程度上達到了多類型適應的目的,但是不徹底,且有二義性存在。
#include <iostream>using namespace std;void myswap(int & a, int &b)
{ int t = a; a = b; b = t;}
void myswap(double & a, double &b)
{ double t = a; a = b; b = t;}
int main()
{ long a = 2; long b = 3; myswap(a,b); //ambiguous cout<<a<<b<<endl; return 0;}
函數模板
文法:在一個函數的參數表, 傳回型別和函數體中使用參數化類別型。
template<typename/class 型別參數 T1, typename/class 型別參數 T2,...>
特點:結構上與普通函數無異,但是在傳入參數和傳回值上做了泛化
傳回型別 函數模板名(函數參數列表){函數模板定義體}
案例:(概念比較抽象,請通過案例來觀察其特點)
關於類型,今後我們會在部落格的迭代中說明,多個不同型別參數的情況如何處理。
函數模板與普通函數的區別無非就是將函數參數高度抽象化,使其具備處理更多資料類型的能力。
特性小結
1)嚴格匹配,不存在隱式轉化。
2)先執行個體化,再調用。
3)型別參數可以省略。
4)尺有所長,寸有所短。
原理:
編譯器並不是把函數模板處理成能夠處理任意類的函數; 編譯器從函數模板通過
具體類型產生不同的函數; 編譯器會對函數模板進行兩次編譯: 在聲明的地方對模板
代碼本身進行編譯, 在調用的地方對參數替換後的代碼進行編譯。
函數模板的應用——將快速排序演算法實現模板化
#include <iostream>#include <typeinfo>using namespace std;
template<typename T>void quickSort(T * array,int left, int right){ if(left<right) { int low = left; int high = right; T pivot = array[low]; while(low<high) { while(array[high] >= pivot && high>low ) high--; array[low] = array[high]; while(array[low] <= pivot&& high>low) low++; array[high] = array[low];
}
array[low] = pivot; quickSort(array,left,low-1); quickSort(array,low+1,right); }}
int main(){ int array[10] = {1,3,5,7,2,4,6,8,0,9}; quickSort<int>(array,0,9); for(auto i:array) { cout<<i<<endl; }}
函數模板的預設參數
函數模板,在調用時,先執行個體化為模板函數,然後再調用。當然也可以設定預設類
型的預設值。由於系統強大的自動推導能力,有時預設也沒有太大的意義。
template<typename T = int>void quickSort(T * array,int left, int right)
模板特化
就是在執行個體化模板時,對特定類型的實參進行特殊處理,即執行個體化一個特殊的執行個體版本。
template<typename T> int compare( T &a, T &b)template<> int compare < const char * >( const char* &a, const char* &b)
當以特化定義時的形參使用模板時,將調用特化版本,模板特化分為全特化和偏特
化,函數模板的特化,只能全特化;
比如我們在比較兩個數的大小時:
#include <iostream>#include <string.h>using namespace std;
template<typename T> int compare( T &a, T &b){ if(a > b) return 1; else if(a < b)return -1; else return 0;}
//實參為兩個 char 指標時, 比較的是指標的大小,//而不是指標指向內容的大小, 此時就需要為該函數模板定義一個特化版本, 即特殊處理的版本:template<> int compare < const char * >( const char* &a, const char* &b){ return strcmp(a,b);}
int main(){ int a = 3; int b = 5; cout<<compare(a,b)<<endl; string str1 = "abc",str2 ="abc"; cout<<compare(str1,str2)<<endl; char * p1 = "abc",*p2= "def"; cout<<compare(p1,p2)<<endl; cout<<compare(p2,p1)<<endl; return 0;}
關於模板特化的認識
模板特化的原因:當前函數模板的邏輯或者功能,不能滿足特定參數的需求。
模板特化的方式:將需要特化的參數提前”布置“到模板中去,提前預定模板,之後傳入需要特化的參數時便可以
優先調用經過該參數特化的模板。
適用情境
函數模板,只適用於函數的參數個數相同而類型不同,且函數體相同的情況。如果
個數不同,則不能用函數模板。
C++泛型程式設計之函數模板