1.泛型的基本思想
ios
泛型編程(Generic Programming)是一種語言機制,經過它能夠實現一個標準的容器庫。像類同樣,泛型也是一種抽象數據類型,可是泛型不屬於面向對象,它是面向對象的補充和發展。
在面向對象編程中,當算法與數據類型有關時,面向對象在對算法的抽象描述方面存在一些缺陷。
好比對棧的描述:
class stack
{算法
push(參數類型) //入棧算法編程
pop(參數類型) //出棧算法數據結構
}
若是把上面的僞代碼看做算法描述,沒問題,由於算法與參數類型無關。可是若是把它寫成可編譯的源代碼,就必須指明是什麼類型,不然是沒法經過編譯的。使用重載來解決這個問題,即對N種不一樣的參數類型寫N個push和pop算法,這樣是很麻煩的,代碼也沒法通用。
若對上面的描述進行改造以下:
首先指定一種通用類型T,不具體指明是哪種類型。
class stack<參數模板 T>
{函數
push(T) //入棧算法spa
pop(T) //出棧算法對象
}內存
這裏的參數模板T至關於一個佔位符,當咱們實例化類stack時,T會被具體的數據類型替換掉。
若定義對象S爲statc類型,在實例化S時若咱們將T指定int型則:
這時候類S就成爲:
class S
{
push(int) //入棧算法
pop(int) //出棧算法
}
這時我能夠稱class stack<參數模板 T>是類的類,經過它能夠生成具體參數類型不一樣的類。ci
2.泛型在C++中的應用
編譯器
泛型在C++中的主要實現爲模板函數和模板類。
一般使用普通的函數實現一個與數據類型有關的算法是很繁瑣的,好比兩個數的加法,要考慮不少類型:
int add(int a,int b) { return a+b; }
float add(float a,float b) { return a+b; }
。。。。
雖然在C++中能夠經過函數重載來解決這個問題,可是反覆寫相同算法的函數是比較辛苦的,更重要的是函數重載是靜態編譯,運行時佔用過多內存。
在此咱們能夠用C++的模板函數來表達通用型的函數,以下:
template<typename T> // 模板聲明
T add(T a,T b) { return a+b; } // 注意形參和返回值的類型
這時C++編譯器會根據add函數的參數類型來生成一個與之對應的帶具體參數類型的函數並調用。
例如:
#include <iostream>
using namespace std;
template <typename T>
T add(T a,T b) //注意形參和返回類型
{
return a+b;
}
void main()
{
int num1, num2, sum;
cin>>num1>>num2;
sum=add(num1,num2); //用int匹配模版參數T,若sum,num1,num2類型不一致則沒法匹配。
cout<<sum;
}
3.函數模板的性質
1) 函數模板並非真正的函數,它只是C++編譯生成具體函數的一個模子。
2) 函數模板自己並不生成函數,實際生成的函數是替換函數模板的那個函數,好比上例中的add(sum1,sum2),
這種替換是編譯期就綁定的。
3) 函數模板不是隻編譯一份知足多重須要,而是爲每一種替換它的函數編譯一份。
4) 函數模板不容許自動類型轉換。
5) 函數模板不能夠設置默認模板實參。好比template <typename T=0>不能夠。
4.C++模版函數的語法
template <typename 模版參數列表…>
函數返回類型 函數名(形參列表…)
上面兩行能夠合併成一行。
例如:
下面的幾種寫法是等效的而且class 和typename是能夠互換的。
template <typename T1, typename T2>
T1 fun(T1, T2, int )
{ //…..}
template <typename T1,T2> T1 fun(T1, T2, int )
{ //…..}
template <class T1, class T2>
T1 fun(T1, T2, int )
{ //…..}
template <class T1,T2> T1 fun(T1, T2, int )
{ //…..}
5.C++模版類的語法
template <class 模版參數列表…>
class 類名
{ //類體}
成員的實現…
例如:
//類聲明部分,有兩個模板參數T1,T2
template <class T1, class T2 >
class A {
private:
int a;
T1 b; //成員變量也能夠用模板參數
public:
int fun1(T1 x, int y );
T2 fun2(T1 x, T2 y);
}
//類實現部分
template <class T1, class T2 >
int A<T1>:: fun1(T1 x, int y ){//實現…… }
template <class T1, class T2 >
T2 A<T1,T2>:: fun2(T1 x, T2 y) {//實現…… }
//使用類A
int main( ) {
//定義對象a,並用int替換T1, float替換T2
A<int, float> a;
//實例化a,調用a的屬性和方法……
}
由上例能夠看出, 類模板參數T1,T2對類的成員變量和成員函數均有效。
在C++編程中,當你要實現的一個類的某些成員函數和成員變量的算法跟數據類型有關,能夠考慮用類模板,且C++版的數據結構算法大都用類模板實現。
6.類模板的性質
1) 類模板不是真正的類,它只是C++編譯器生成具體類的一個模子。2) 類模板能夠設置默認模板實參。