STL模板的基礎與了解
一·C++提供了模版的編程方法來解決編程問題,思路是:程序員先編號一份“套路”代碼,然後在調用時編譯器根據調用時的參數
再為這種數據類型生成一份屬於他的代碼
C語言中的快速排序:
void qsort(void *base, size_t nmemb, size_t size,int(*compar)(const void *, const void *))
二.模板的語法
template <typename T,typename M>
T max(T num1,M num2)
{
return num1>num2?num1:num2;
}
a.模版的類型參數
T 被稱為模版的類型參數,可以叫任何名字,只是俗稱約定叫做T
它指的是函數調用時的任意類型的參數
雖然模版的類型可以是任意的,但是必須要支持模版函數中所使用到的運算符,模版不是萬能的,雖然能帶來好處
但也帶來了很多問題
b.函數模版的使用
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 classname<T>::num = 10;
靜態成員必須在類模版實例化後才被正真定義出來,每個實例化的類都有一份靜態成員,這個實例化類創建出的
對象公用一個靜態成員
e.遞歸實例化
classname<classname<int>> 對象
六.類模版的特化(重載)
特化:當類模版不能特殊的類型無法處理時,可以為這種特殊類型單獨實例化一個類,這個單獨的實現叫做模版的特化
全類的特化:按照類的格式把類完整的實現一遍(重寫一遍)
template <> class className <返回值類型>
{
......
};
成員特化:給制定類型提供一個特殊的成員函數
template <> 返回值類型 className<返回值類型>:max(void)
{
....
}
局部特化:可以讓用戶根據實例化時的參數來指定所使用的類模版
同等程度的特化會產生二異性
七.類模版的參數
1. 類模版的參數可以有默認值
註意:使用類模版默認值時,<>必須加上,可以空著,但不能不寫
2. 類模版後面的參數可以調用前邊的參數
3. 普通數值可以對類模版進行實例化,它必須以類似變量的形式存在
註意:只能常量才能進行實例化,
STL模板的基礎與了解