???? 模板按其使用,可歸結為兩大類:函數模板和類模板。函數模板和普通函數相比,可謂異曲同工。普通函數也算得上是一種模板,只是施加于普通函數上的限制嚴格于函數模板而已。普通函數實現了基本的算法,調用函數時,需提供相同數目,相同類型的實參來代替形參。而模板函數除了要求參數的數目相同外,將形參的類型作了放大,因而其使用范圍也隨之變大。模板函數的實參類型只需要具有形參類型所必須的操作即可。
???? 下面的例子定義了三個函數:
?1
//max.h
?2
#include?<iostream>
?3
template?<typename?T>
?4
inline?T?const&?max(T?const&?a,T?const&?b)
{
?5
????std::cout<<"你調用的是兩個參數的模板函數!"<<std::endl;
?6
????return?a>b?a:b;
?7
}
?8
?9
template?<typename?T1,typename?T2>
10
inline?T1?const&?max(T1?const&?a,T2?const&b)
{
11
????std::cout<<"你調用的是兩個參數的模板函數,且參數類型不同!"<<std::endl;
12
????return?a>b?a:b;
13
}
14
15
inline?int?const&?max(int?const&?a,int?const&?b)
{
16
????std::cout<<"你調用的是兩個參數的普通函數!"<<std::endl;
17
????return?a>b?a:b;
18
}
19
20
template?<typename?T>
21
inline?T?const&?max(T?const&?a,?T?const&?b?,T?const&?c)
{
22
????std::cout<<"你調用的是三個參數的模板函數!"<<std::endl;
23
????T?d;
24
????d=a>b?a:b;
25
????return?d>c?d:c;
26
}
27

?2

?3

?4



?5

?6

?7

?8

?9

10



11

12

13

14

15



16

17

18

19

20

21



22

23

24

25

26

27

?1
#include?<iostream>
?2
#include?<string>
?3
#include?"max.h"
?4
?5
int?main()
{
?6
????int?i=42;
?7
????std::cout<<"max(7,i)?is?"<<::max(7,i)<<std::endl;
?8
?9
????double?f1=3.45;
10
????double?f2=-9.34;
11
????std::cout<<"max(f1,f2)?is"<<::max(f1,f2)<<std::endl;
12
????
13
????//下面的兩行代碼是正確的,前者明確指明參數的類型;后者通過類型轉換都使得代碼能正確運行。
14
????std::cout<<"max(f1,i)?is"<<::max<double>(f1,i)<<std::endl;
15
????std::cout<<"max(f1,i)?is"<<::max(f1,static_cast<double>(i))<<std::endl;
16
17
????std::cout<<"max(f1,f2,f3)"<<::max(12.0,13.0,11.5)<<std::endl;
18
????std::cout<<"max(char,int)"<<::max('a',12)<<std::endl;
19
????std::cout<<"max(f1,i)?is"<<::max(f1,i)<<std::endl;
20
????std::cout<<"max(int,int)"<<::max<double>(12,34)<<std::endl;
21
????std::cin>>i;
22
}

?2

?3

?4

?5



?6

?7

?8

?9

10

11

12

13

14

15

16

17

18

19

20

21

22

???? 上面的代碼說明了模板函數的定義、模板函數的重載和使用等方面的問題,比較有意思的是模板函數的重載。和普通函數一樣,模板函數也能重載,可以為模板函數定義參數數目不同的重載函數,也可以定義數目相同但參數類型不同的重載函數,而普通函數我們也可以當作是指定了具體類型的模板函數來處理。經過這樣的處理,我們可以看出,模板函數的重載和普通函數的重載方式大同小異。
???? 說完了模板函數的重載,我們再談談重載模板函數的使用,使用模板函數時,采用最符合原則進行調用,這也是為什么第14行的代碼調用的是普通函數,而18,19行的代碼調用的是兩個參數類型不同的模板函數的原因。如果我們將第18,19行代碼調用的模板函數去掉,那么代碼仍然可以運行,其調用的將是普通函數,因為char和float都可以轉換為int,最符合的函數原型是普通函數。
????
???? 我們繼續前面的話題。模板函數還是十分簡單的,模板類則復雜的多。同模板函數一樣,也能對模板類實施重載。當然,對類而言,使用重載似乎不是那么合適了,因而我們使用專門的詞來稱呼-專門化(Specialization)。而這種specialization,同模板函數重載一樣,可以是完全specialization,也可是部分specialization(partial specialization),其實我們完全可以沿用前面處理函數的觀點,將普通類(完全specialization的類)當作是一種特殊的模板類,那樣無論是何種specialization,事實上都是模板類,只是類型參數的限制不同而已。如果進行這樣的統一以后,對于重載模板類的定義、使用就同模板函數完全一致了,這里就不再多費口舌了。
???? 模板類有一個模板函數不具有的特性-默認參數類型。模板類的類型參數設定時可以給出默認類型,使用的時候如果對于該參數不給出實參類型,將使用默認類型代替形參類型,這同函數中的默認參數值是一樣的,不過模板函數是不允許這樣做的。