模板概述
                            
                            
                            ???? 模板,按建筑學(xué)的說法是:施工時(shí)澆筑混凝土用的成組模型板;而模板之詞,恐怕可釋之為模型之板,顧名思義,模板為一套規(guī)定好了規(guī)范準(zhǔn)則的樣板。既然為樣板,自然是可被多方使用;而準(zhǔn)則既已定好,那么限制亦是必然存在呢。程序界中的模板,原義也應(yīng)取于此。模板所用之樣板根據(jù)模板的不同可為實(shí)現(xiàn)了一定算法的函數(shù),也可為規(guī)定好了內(nèi)部數(shù)據(jù)結(jié)構(gòu)和操作的類;而所施加之限制則為合乎模板定義的類型參數(shù)。至于模板定義的類型參數(shù),不外乎:數(shù)目相同、操作完備呢。
???? 模板按其使用,可歸結(jié)為兩大類:函數(shù)模板和類模板。函數(shù)模板和普通函數(shù)相比,可謂異曲同工。普通函數(shù)也算得上是一種模板,只是施加于普通函數(shù)上的限制嚴(yán)格于函數(shù)模板而已。普通函數(shù)實(shí)現(xiàn)了基本的算法,調(diào)用函數(shù)時(shí),需提供相同數(shù)目,相同類型的實(shí)參來代替形參。而模板函數(shù)除了要求參數(shù)的數(shù)目相同外,將形參的類型作了放大,因而其使用范圍也隨之變大。模板函數(shù)的實(shí)參類型只需要具有形參類型所必須的操作即可。
???? 下面的例子定義了三個(gè)函數(shù):
?1//max.h
?2#include?<iostream>
?3template?<typename?T>
?4inline?T?const&?max(T?const&?a,T?const&?b){
?5????std::cout<<"你調(diào)用的是兩個(gè)參數(shù)的模板函數(shù)!"<<std::endl;
?6????return?a>b?a:b;
?7}
?8
?9template?<typename?T1,typename?T2>
10inline?T1?const&?max(T1?const&?a,T2?const&b){
11????std::cout<<"你調(diào)用的是兩個(gè)參數(shù)的模板函數(shù),且參數(shù)類型不同!"<<std::endl;
12????return?a>b?a:b;
13}
14
15inline?int?const&?max(int?const&?a,int?const&?b){
16????std::cout<<"你調(diào)用的是兩個(gè)參數(shù)的普通函數(shù)!"<<std::endl;
17????return?a>b?a:b;
18}
19
20template?<typename?T>
21inline?T?const&?max(T?const&?a,?T?const&?b?,T?const&?c){
22????std::cout<<"你調(diào)用的是三個(gè)參數(shù)的模板函數(shù)!"<<std::endl;
23????T?d;
24????d=a>b?a:b;
25????return?d>c?d:c;
26}
27???? 其中,第一和第三個(gè)函數(shù)都為模板函數(shù),而第二個(gè)函數(shù)為普通函數(shù)。下面的代碼使用這些函數(shù):
?1#include?<iostream>
?2#include?<string>
?3#include?"max.h"
?4
?5int?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????//下面的兩行代碼是正確的,前者明確指明參數(shù)的類型;后者通過類型轉(zhuǎn)換都使得代碼能正確運(yùn)行。
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} ???? 通過上面的代碼的運(yùn)行結(jié)果,我們可以發(fā)現(xiàn)第14行的代碼調(diào)用的都是普通函數(shù)版本的max函數(shù),而第18、19行的代碼調(diào)用的是兩個(gè)參數(shù)類型不同的模板函數(shù)。
???? 上面的代碼說明了模板函數(shù)的定義、模板函數(shù)的重載和使用等方面的問題,比較有意思的是模板函數(shù)的重載。和普通函數(shù)一樣,模板函數(shù)也能重載,可以為模板函數(shù)定義參數(shù)數(shù)目不同的重載函數(shù),也可以定義數(shù)目相同但參數(shù)類型不同的重載函數(shù),而普通函數(shù)我們也可以當(dāng)作是指定了具體類型的模板函數(shù)來處理。經(jīng)過這樣的處理,我們可以看出,模板函數(shù)的重載和普通函數(shù)的重載方式大同小異。
???? 說完了模板函數(shù)的重載,我們再談?wù)勚剌d模板函數(shù)的使用,使用模板函數(shù)時(shí),采用最符合原則進(jìn)行調(diào)用,這也是為什么第14行的代碼調(diào)用的是普通函數(shù),而18,19行的代碼調(diào)用的是兩個(gè)參數(shù)類型不同的模板函數(shù)的原因。如果我們將第18,19行代碼調(diào)用的模板函數(shù)去掉,那么代碼仍然可以運(yùn)行,其調(diào)用的將是普通函數(shù),因?yàn)閏har和float都可以轉(zhuǎn)換為int,最符合的函數(shù)原型是普通函數(shù)。
????說完了函數(shù)模板,該談?wù)勀0孱惲?#xff0c;可惜肚子開始呱呱叫了,只好下回分解呢。?
???? 我們繼續(xù)前面的話題。模板函數(shù)還是十分簡單的,模板類則復(fù)雜的多。同模板函數(shù)一樣,也能對模板類實(shí)施重載。當(dāng)然,對類而言,使用重載似乎不是那么合適了,因而我們使用專門的詞來稱呼-專門化(Specialization)。而這種specialization,同模板函數(shù)重載一樣,可以是完全specialization,也可是部分specialization(partial specialization),其實(shí)我們完全可以沿用前面處理函數(shù)的觀點(diǎn),將普通類(完全specialization的類)當(dāng)作是一種特殊的模板類,那樣無論是何種specialization,事實(shí)上都是模板類,只是類型參數(shù)的限制不同而已。如果進(jìn)行這樣的統(tǒng)一以后,對于重載模板類的定義、使用就同模板函數(shù)完全一致了,這里就不再多費(fèi)口舌了。
???? 模板類有一個(gè)模板函數(shù)不具有的特性-默認(rèn)參數(shù)類型。模板類的類型參數(shù)設(shè)定時(shí)可以給出默認(rèn)類型,使用的時(shí)候如果對于該參數(shù)不給出實(shí)參類型,將使用默認(rèn)類型代替形參類型,這同函數(shù)中的默認(rèn)參數(shù)值是一樣的,不過模板函數(shù)是不允許這樣做的。
                        
                        
                        ???? 模板按其使用,可歸結(jié)為兩大類:函數(shù)模板和類模板。函數(shù)模板和普通函數(shù)相比,可謂異曲同工。普通函數(shù)也算得上是一種模板,只是施加于普通函數(shù)上的限制嚴(yán)格于函數(shù)模板而已。普通函數(shù)實(shí)現(xiàn)了基本的算法,調(diào)用函數(shù)時(shí),需提供相同數(shù)目,相同類型的實(shí)參來代替形參。而模板函數(shù)除了要求參數(shù)的數(shù)目相同外,將形參的類型作了放大,因而其使用范圍也隨之變大。模板函數(shù)的實(shí)參類型只需要具有形參類型所必須的操作即可。
???? 下面的例子定義了三個(gè)函數(shù):
?1//max.h
?2#include?<iostream>
?3template?<typename?T>
?4inline?T?const&?max(T?const&?a,T?const&?b){
?5????std::cout<<"你調(diào)用的是兩個(gè)參數(shù)的模板函數(shù)!"<<std::endl;
?6????return?a>b?a:b;
?7}
?8
?9template?<typename?T1,typename?T2>
10inline?T1?const&?max(T1?const&?a,T2?const&b){
11????std::cout<<"你調(diào)用的是兩個(gè)參數(shù)的模板函數(shù),且參數(shù)類型不同!"<<std::endl;
12????return?a>b?a:b;
13}
14
15inline?int?const&?max(int?const&?a,int?const&?b){
16????std::cout<<"你調(diào)用的是兩個(gè)參數(shù)的普通函數(shù)!"<<std::endl;
17????return?a>b?a:b;
18}
19
20template?<typename?T>
21inline?T?const&?max(T?const&?a,?T?const&?b?,T?const&?c){
22????std::cout<<"你調(diào)用的是三個(gè)參數(shù)的模板函數(shù)!"<<std::endl;
23????T?d;
24????d=a>b?a:b;
25????return?d>c?d:c;
26}
27???? 其中,第一和第三個(gè)函數(shù)都為模板函數(shù),而第二個(gè)函數(shù)為普通函數(shù)。下面的代碼使用這些函數(shù):
?1#include?<iostream>
?2#include?<string>
?3#include?"max.h"
?4
?5int?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????//下面的兩行代碼是正確的,前者明確指明參數(shù)的類型;后者通過類型轉(zhuǎn)換都使得代碼能正確運(yùn)行。
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} ???? 通過上面的代碼的運(yùn)行結(jié)果,我們可以發(fā)現(xiàn)第14行的代碼調(diào)用的都是普通函數(shù)版本的max函數(shù),而第18、19行的代碼調(diào)用的是兩個(gè)參數(shù)類型不同的模板函數(shù)。
???? 上面的代碼說明了模板函數(shù)的定義、模板函數(shù)的重載和使用等方面的問題,比較有意思的是模板函數(shù)的重載。和普通函數(shù)一樣,模板函數(shù)也能重載,可以為模板函數(shù)定義參數(shù)數(shù)目不同的重載函數(shù),也可以定義數(shù)目相同但參數(shù)類型不同的重載函數(shù),而普通函數(shù)我們也可以當(dāng)作是指定了具體類型的模板函數(shù)來處理。經(jīng)過這樣的處理,我們可以看出,模板函數(shù)的重載和普通函數(shù)的重載方式大同小異。
???? 說完了模板函數(shù)的重載,我們再談?wù)勚剌d模板函數(shù)的使用,使用模板函數(shù)時(shí),采用最符合原則進(jìn)行調(diào)用,這也是為什么第14行的代碼調(diào)用的是普通函數(shù),而18,19行的代碼調(diào)用的是兩個(gè)參數(shù)類型不同的模板函數(shù)的原因。如果我們將第18,19行代碼調(diào)用的模板函數(shù)去掉,那么代碼仍然可以運(yùn)行,其調(diào)用的將是普通函數(shù),因?yàn)閏har和float都可以轉(zhuǎn)換為int,最符合的函數(shù)原型是普通函數(shù)。
????說完了函數(shù)模板,該談?wù)勀0孱惲?#xff0c;可惜肚子開始呱呱叫了,只好下回分解呢。?
???? 我們繼續(xù)前面的話題。模板函數(shù)還是十分簡單的,模板類則復(fù)雜的多。同模板函數(shù)一樣,也能對模板類實(shí)施重載。當(dāng)然,對類而言,使用重載似乎不是那么合適了,因而我們使用專門的詞來稱呼-專門化(Specialization)。而這種specialization,同模板函數(shù)重載一樣,可以是完全specialization,也可是部分specialization(partial specialization),其實(shí)我們完全可以沿用前面處理函數(shù)的觀點(diǎn),將普通類(完全specialization的類)當(dāng)作是一種特殊的模板類,那樣無論是何種specialization,事實(shí)上都是模板類,只是類型參數(shù)的限制不同而已。如果進(jìn)行這樣的統(tǒng)一以后,對于重載模板類的定義、使用就同模板函數(shù)完全一致了,這里就不再多費(fèi)口舌了。
???? 模板類有一個(gè)模板函數(shù)不具有的特性-默認(rèn)參數(shù)類型。模板類的類型參數(shù)設(shè)定時(shí)可以給出默認(rèn)類型,使用的時(shí)候如果對于該參數(shù)不給出實(shí)參類型,將使用默認(rèn)類型代替形參類型,這同函數(shù)中的默認(rèn)參數(shù)值是一樣的,不過模板函數(shù)是不允許這樣做的。
轉(zhuǎn)載于:https://www.cnblogs.com/lotusswan/archive/2005/09/01/227727.html
總結(jié)
                            
                        - 上一篇: 学习单调队列小结
 - 下一篇: 劫的E附带平A伤害是指E的时候有平A伤害