1. 程式人生 > >STL模板初步學習

STL模板初步學習

類型 第一次 stl 方法 創建 翻譯 max typename 編寫

一、如何進行泛型編程
C/C++是一種靜態編程語言,必須需要把代碼翻譯成可執行的二進制可執行程序然後再運行,一旦編譯好之後就不能再變了(數據類型也就必須確定下無法更改,因此要為每一種數據類型編寫一份算法,工程量巨大)

C語言中的快速排序
void qsort(void *base, size_t nmemb, size_t size,
int(*compar)(const void *, const void *));

C++提供了模板編程方法來解決泛型編程的問題,它的解決思路是,程序員先編寫好一份"套路"代碼,然後在調用編譯器時根據調用時的參數再為這中數據類型生成一份屬於它的代碼

二、模板的語法
template<typename T,typename M>
T max(T num1,M num2)
{
return num1>num2?num1:num2;
}

模版的類型參數
    T被稱作模板的類型參數,可以叫任何名字,只是俗稱約定叫做T
    它指的是函數調用時的任何類型參數

雖然模板的類型可以是任意的,但是必須要支持模板函數中所使用到的運算符,因此模板不是萬能的,雖然能帶來好處,但也帶來許多問題

三、函數模板的使用
1、模板的實例化
編譯器不會把函數模板編譯成一個實例,而是根據調用時的參數,再進行實例化(進一步生成二進制指令)

2、使用模板時才實例化
模板只有在調用時才會實例化,因此模板編譯正確並不代表沒有問題,很多錯誤會產生於調用時


3、二次編譯
第一次是檢查模版的語法,第二次編譯是根據調用參數把模板實例化出來,然後再檢查運算符是否支持這種類型


四、函數模板的隱式推斷
a、使用函數模板時可以根據參數的類型來推斷模板的參數
b、當函數模板不能通過函數調用時的參數來推斷模板參數時,可以使用<類型,類型...>來明確指定
c、模版參數可以有默認值的
   1、默認值優先放在右邊
    2、C++標準才支持:-std=c++0x

五、函數模板與普通可以重載(特化)
1、同一種格式的函數和函數模板是可以共生,但優先調用普通函數,但可以有函數名後添加一個空的<>指定調用函數模板,模板參數根據調用時的參數推斷

2、普通函數在調用時可以進行類型提升,但是這種提升的結果要低於模板的實例化

3、函數模板也可以進行類型提升,但如果有一個普通函數也可以進行類型提升調用,那麽則優先調用普通函數


六、類模板
a、類模板的語法
類模板的參數可以在類中當作類型使用,可以定義成員、返回值、參數等。
template<class T,class A,class B,...>
class className
{
C c;
public:
T func(A a);
};
註意:typename也可以繼續使用,但大多用class以示區別。

b、類模板的使用
類模板必須要經過實例化才能使用,也是需要經過兩次編譯,第一次是把類模板編譯成一個"套路",這個過程是為了檢查語法,第二次是根據實例化參數,生成一個類,然後才能使用這個類創建對象。

使用類模板實例化一個類:
className<type1,type2,...> a;

練習:實現棧類模板,成員函數有入棧、出棧、棧空、棧滿。

c、類模板參數不支持隱式推斷,必須顯示實例化。

d、靜態成員的定義的語法
template<class T> int MyStack<T>::num = 10;
靜態成員必須在類模板實例化之後才被真正定義出來,每個實例化的類都有和份靜態成員,這個實例化類創建出的對象共用一個靜態成員。

e、遞歸實例化
MyStack<MyStack<int>> stack;
盡量不要輕易使用。

七、類模板的特化(重載)
特化:指的是當類模板有特殊的類型無法處理時,可以為這種特殊類型單獨實例化出一個類,這種單獨的實現叫作模板的特化。

全類的第特化:按照類的格式把類完整再實現一遍(重寫一遍)。

template<> class className <char*>
{
...
};

成員特化:給指定的類型提供一個特殊的的成員函數。
template<> 返回值 className<char*>::max(void)
{
...
}

局部特化:可以讓用戶根據實例化時的參數來指定使用的類模板
template<class A,class B> class N
{public:N(void){cout <<"1"<<endl;}};
template<class A> class N <A,A>
{public:N(void){cout <<"2"<<endl;}};
template<class A> class N <A,short>
{public:N(void){cout <<"3"<<endl;}};
template<class A> class N <A*,A*>
{public:N(void){cout <<"4"<<endl;}};
template<class A,class B> class N <A*,B*>
{public:N(void){cout <<"5"<<endl;}};

註意:同等程序的特化會引起二義性。

八、類模板的參數
1、類模板的參數可以有默認值
註意:使用類模板默認值時,<>不能省略,可以空著,但不能不寫。
2、類模板後面的參數可以調用前面的參數。

3、普通數值可以對類模板進行實例化,它必須以類似變量的形式存在。
註意:只能是常量才能進行實例化。




STL模板初步學習