泛型程式設計:編寫與型別無關的通用**,是**復用的一種手段。模板是泛型程式設計的基礎。
函式模板代表了乙個函式家族,該函式模板與型別無關,在使用時被引數化,根據實參型別產生函式的特定型別版本。
模板的格式
template
返回值型別 函式名(引數列表){}
模板分為類模板和函式模板
模板它本身並不是函式,是編譯器用使用方式產生特定具體型別函式的模具。所以其實模板就是將本來應該我們做的重複做的事交給了編譯器
在編譯器編譯階段,對於模板函式的使用,編譯器需要根據傳入的實參型別來推演生成對應型別的函式以供呼叫。比如:當用double型別使用函式模板時,編譯器通過對實參型別的推演,將t確定為double型別,然
後產生乙份專門處理double型別的**,對於字元型別也是如此.
模板的例項化
用不同型別引數使用函式模板時,稱為模板的例項化
模板的例項化分為:1隱式例項化2顯示例項化
1隱式例項化:讓編譯器根據實參自己推演模板引數的實際型別
一.函式模板
templatet add(const t& left, const t& right)
int main()
該語句不能通過編譯,因為在編譯期間,當編譯器看到該例項化時,需要推演其實參型別
通過實參a1將t推演為int,通過實參d1將t推演為double型別,但模板引數列表中只有乙個t,
編譯器無法確定此處到底該將t確定為int 或者 double型別而報錯
在模板中,編譯器一般不會進行型別轉換操作,
add(a,(int)d)–強制型別轉換
2顯示例項化
在函式名後的<>中指定模板引數的實際型別
int main(void)
如果型別不匹配編譯器會進行隱式型別轉換
模板的匹配原則
1. 乙個非模板函式可以和乙個同名的函式模板同時存在,而且該函式模板還可以被例項化為這個非模板函式
int add(int left, int right)
templatet add(t left, t right)
void test()
3. 模板函式不允許自動型別轉換,但普通函式可以進行自動型別轉換
二.類模板
template
class 類模板名
;eg;
template
class vector
~vector();//析構在類裡面宣告類外定義
private:
size_t _capacity;
size_t _size;
t* _data;
};//類模板放在類外需要加模板引數列表
template
vector::~vector()
_size = _capacity = 0;
}int main()
const t& operator(size_t index)const
size_t size()
bool isempty()
private:
t _arry[n];
size_t _size;
};浮點數、類物件以及字串是不允許作為非型別模板引數的。非型別的模板引數必須在編譯期就能確認結果。
模板的特化
使用模板可以實現一些與型別無關的**,但對於一些特殊型別的可能會得到一些錯誤的結
果,比如:
templatebool issame(const t1& a, const t2& b)
int main()
當為char型別需要進行單獨處理也就是需要對模板進行特化。即:在原模板類的基礎上,針對特殊型別所進行特殊化的實現方式。模板特
化中分為函式模板特化與類模板特
函式模板特化
(1)必須要有基礎的函式模板
(2)關鍵字template後面接一對空的尖括號<>括號,尖括號中指定需要特化的型別
(3). 函式形參表: 必須要和模板函式的基礎引數型別完全相同,如果不同編譯器可能會報一些奇怪的錯誤。
template<>
bool issame(char*& left, char*& right)
一般情況下如果函式模板遇到不能處理或者處理有誤的型別,為了實現簡單通常都是將該函式直接給出。也就是不用特化直接實現
類模板的特化
全特化全特化即是將模板引數類表中所有的引數都確定化。
templateclass data
偏特化
任何針對模版引數進一步進行條件限制設計的特化版本。比如對於以下模板類
偏特化有以下兩種表現方式:
部分特化
將模板引數類表中的一部分引數特化。
// 將第二個引數特化為int
template class data
模板不支援分離編譯
// a.h
template t add(const t& left, const t& right);
// a.cpp
template t add(const t& left, const t& right)
// main.cpp
#include"a.h"
int main()
結果會出現
分離編譯–>鏈結錯誤–>無法解析的外部命令
鏈結錯誤和編譯錯誤區別:
鏈結錯誤不是語法錯誤,1函式和變數(更多函式)找不到函式位址,找不到變數和函式的定義,
編譯是檢測語法錯誤
預處理:替換巨集,條件編譯,展開標頭檔案,去注釋,#include(標頭檔案通常是宣告也有可能有定義).h被展到對應的.cpp中, linux a.i a.i
2編譯:檢查語法,生成彙編** a.s a.s
3彙編:把彙編**轉化成機器碼linux vector.o a.o windows obj
4鏈結生成可執行程式 a.out exe
模板分離的時候用的時候例項化鏈結的時候沒有編譯找不到他的實現,但是也不是完全不能,問題就是沒有例項化,但是例項化在用的時候才會,在鏈結之前是沒有相交的
解決方法
顯示例項化
template a
宣告和定義放到.h譯直接有它的定義和宣告了
模板優缺點分析:
模板復用了**,節省資源,更快的迭代開發,c++的標準模板庫(stl)因此而產生
增強了**的靈活性
缺點模板會導致**膨脹問題,也會導致編譯時間變長
出現模板編譯錯誤時,錯誤資訊非常凌亂,不易定位
了解類模板的型別萃取
模板與泛型程式設計
模板是泛型變成的基礎。泛型程式設計 編譯與型別無關的 是一種復用的方式,模板分為模板函式和模板類。模板函式是乙個通用的函式模板,而不是為每一種型別定義乙個新函式,乙個函式模板就像乙個公式,針對不同型別函式生成不同的函式版本。關鍵字 template 以 template 開始,後面跟乙個模板引數列表...
模板與泛型程式設計
一 函式模板 模板定義以關鍵字template開始,後跟乙個模板引數列表,在模板定義中,模板引數列表不能為空。模板型別引數 型別引數前必須使用class或typename關鍵字。非型別模板引數 表示乙個值而不是乙個型別 陣列引用形參 arr兩端的括號必不可少 void print int arr 1...
7 模板與泛型程式設計
understanding implicit inte ces and compile time polymorphism.編譯期多型 模板根據型別例項化 過載函式。執行期多型 執行時決定那個乙個virtual函式被呼叫。understand the two meanings of typename...