一、函式模板
1、定義:
代表了乙個函式家族,該函式與型別無關,在使用時被引數化,根據實參型別產生函式的特定型別版本。
2、格式:
template
//但是建議使用
typename
,避免和
class
類混淆
template 《型別1變數1, 型別2 變數2, ….. > 返回型別 函式名(形參表)
3、作用域
typedef
intt;
template
t>
t add(t
left,t
right)
//t的作用域在模板形參之後到模板宣告或定義的末尾之間使用,遵循名字遮蔽規則。
t global ;此處的t是全域性的typedef的 int t;
4、編譯:
模板被一共被編譯了兩次:
第一階段:例項化之前,檢查模板**本身,看看模板是否出現語法錯誤,如:忘記分號或者變數名拼錯,並檢查引數型別是否匹配,在此階段,編譯器只能檢查部分的錯誤。
5、例項化:
template
t add(t left, t right)
cout << add('1', '2')<
cout << add(1, '1') <
cout << add(1, '1') << endl;//
編譯不通過
二.模板形參:(型別形參和非型別形參)
型別形參:
1、型別形參轉換:(編譯器只會執行兩種轉換)
(1)const轉換:接受const引用或者const指標的函式可以分別用非const物件的引用或者指標來呼叫。
template
void funtest(constt&p)//
本來應該是
const int *p
而實際是
int*const p,
(2)陣列或函式到指標的轉換:如果模板形參不是引用型別,則對陣列或函式型別的實參應用常規指標轉換。陣列實參將當做指向第乙個元素的指標,函式實參當做指向函式型別的指標.
void funtest1()
template
void funtest(t p)
int arr[10];
funtest(arr);//
執行結果:
int*
funtest(funtest1);//
執行結果:
void <__cdecl*>
注意:
1、模板形參的名字在同一模板形參列表中只能出現一次。
2、模板形參用<>括起來,且模板形參不能為空,多個形參之間必須加「,」。
3、模板形參可以是型別形參和非型別形參,型別形參必須使用關鍵字class或typename。
4、使用模板型別形參和內建型別或者自定義型別使用方法完全一樣,可用作指定函式形參型別,返回型別,區域性變數和強轉型別轉換。
非模板型別引數:
1、概念:
非型別模板引數,顧名思義,模板引數不限定於型別,普通值也可作為模板引數。它是模板內部定義的常量,在需要常量表示式的時候,可以使用非模板型別。而使用基於常量的模板時,你必須顯式地指定這些值,模板方可被例項化。
2、用途:
乙個非型別引數可以是乙個整型,或者是乙個指向物件或函式型別的指標或引用。
繫結到非型別整型引數的實參必須是乙個常量表示式。繫結到指標或引用非型別引數的實參必須具有靜態的生存期。
3、例如:
template
void funtest(t(&array)[n])
}template
int compare(const
char(&p1)[n],const
char(&p2)[m])
int_array[5];
funtest(_array);/*
000434fc call funtest(041528h) */
char_array1[5];
funtest(_array1);/*
00234518 call funtest(023152dh) */
compare("hi", "hello");
/*編譯器會按照字面常量的大小來代替n和
m,從而例項化模板,
注意:編譯器會在乙個字串字面常量的末尾插入乙個空字元作為終結符,
因此編譯器會例項化處以下版本:
intcompare(const char(&p1)[3], const char(&p2)[6]) ps
:非型別模板引數的模板必須是常量表示式。 */
三、模板函式過載
類似於通函式一樣,模板函式也可以過載。(注意:模板函式既不是函式也不是類)
int _max(intleft,int right)
template
t _max(const t&left, const t & right)
template
t _max(t left, t mid,t right)
int main()
四、模板函式特化
1、原因:
當函式模板需要對某些型別進行特別處理,稱為函式模板的特化。因為,在某些情況下,通用模板定義對於某個型別可能是錯誤的,或者編譯通過不了,即使編譯通過了,也不是我們想要得到的答案,這時候,需要我們對函式模板進行特化。
2、特化格式:
template
<>
返回值 函式名(函式引數列表)
3、例如:
template
//普通函式模板
int is_equal(t t1, t t2)
template
<>//
特化函式模板
int is_equalchar*>(const
char*constp1,const
char*constp2)
const
char*p1 = "bbbb";
const
char*p2 = "aaaa";
cout<< is_equal( p1, p2) << endl;//p1>p2
應該返回
1,而實際結果卻是-1;
//p1 0x0108dc70 "bbbb" char *
//p2 0x0108dc78 "aaaa" char * //
比較時,直接比較的是兩個位址的大小,而沒有比較兩個指標的內容
4、特化位置:
特化必須出現在模板例項的呼叫之前,否則在編譯的時候,找不到特化函式模板,則會按照普通模板函式進行呼叫。
函式模板(泛型程式設計)
函式模板就是將函式型別引數化,方便程式設計。1 普通函式模板 include using namespace std template template是告訴編譯器,要開始泛型程式設計了,並用t替代函式的引數型別 void myswap t a,t b template 定義兩個泛型,其實定義乙個也...
泛型程式設計 函式模板
當函式的業務邏輯相同但是函式的引數不相同時,讓型別引數化,讓程式設計師能夠方便程式設計,就用到了泛型程式設計。基本語法 includeusing namespace std 函式的業務邏輯一樣但是函式的引數不一樣 void myswap01 int a,int b void myswap02 cha...
C 泛型程式設計 函式模板 類模板
以前我們寫過乙個簡單的交換函式。我們不難發現交換函式是與型別有很大關係的,int,double.那麼如何實現乙個通用的交換函式呢?void swap int left,int right void swap double left,double right void swap char left,c...