模板1.0 -- 模板基本原理
為什么需要模板
我們經(jīng)常有這樣的一種使用的情形,就是我們可能需要設(shè)計(jì)一個(gè)函數(shù),然后函數(shù)的參數(shù)可能是整形的,也可能是浮點(diǎn)型的,還有可能是其他的類(lèi)型的,這個(gè)時(shí)候如果對(duì)于每一個(gè)類(lèi)型都寫(xiě)一個(gè)函數(shù),未免有點(diǎn)太復(fù)雜了
我們有以下幾個(gè)方法來(lái)實(shí)現(xiàn)一個(gè)函數(shù)針對(duì)不同的類(lèi)型都能夠?qū)崿F(xiàn)
法一:通過(guò)函數(shù)重載實(shí)現(xiàn)
比如我們想要寫(xiě)一個(gè)相加的函數(shù),我們需要實(shí)現(xiàn)函數(shù)的重載
int Add(const int a,const int b)
{return a+b;
}
double Add(cosnt double a,const double b)
{return a+b;
}
char Add(const char a,const char )缺點(diǎn)分析: 
 1. 一個(gè)類(lèi)出現(xiàn)時(shí)就需要繼續(xù)重載一個(gè)函數(shù) 
 2. 代碼的復(fù)用率低 
 3. 如果一個(gè)函數(shù)只是返回值不同,函數(shù)的重載還解決不了問(wèn)題 
 4. 如果函數(shù)的邏輯錯(cuò)誤了,那么所有的函數(shù)都需要修改,麻煩
法二:使用公共的基類(lèi)
我們可以將重復(fù)的代碼放在一個(gè)公共的基類(lèi),然后進(jìn)行一個(gè)繼承
缺點(diǎn): 
 1. 公共的代碼放在了基類(lèi)里面就缺少了類(lèi)型檢查的優(yōu)點(diǎn)了 
 2. 一個(gè)簡(jiǎn)單的函數(shù),以后使用了繼承之后,以后維護(hù)起來(lái)麻煩
法三:使用宏函數(shù)
#define Add(a,b) ((a)+(b))缺點(diǎn): 
 1. 沒(méi)有了類(lèi)型檢查 
 2. 在預(yù)處理階段就被替換掉了,不方便調(diào)試 
引入模板
C++為了解決上面的問(wèn)題,于是就引入了模板的使用,像下面的形式來(lái)實(shí)現(xiàn)Add函數(shù)的復(fù)用
template<class T>
T Add(const T& a,const T&b)
{return a+b;
}其中我們使用class的時(shí)候,也是可以使用typename這個(gè)關(guān)鍵字的 
 我們?cè)谄渌牡胤秸{(diào)用這個(gè)模板函數(shù)的時(shí)候,就可以使用下面的方式進(jìn)行一個(gè)調(diào)用的過(guò)程
int x = 1;
int y = 2;
double m = 1.0;
double n = 2.0;Add(x,y);
Add(m,n);上面的兩次對(duì)模板函數(shù)的調(diào)用是不是調(diào)用的同一個(gè)函數(shù)呢,答案:不是。他們調(diào)用了不同的函數(shù),這里引入的一個(gè)概念就是模板的實(shí)例化 
 我們經(jīng)常聽(tīng)到的一個(gè)概念是對(duì)象的實(shí)例化,就是我們拿一個(gè)類(lèi)去實(shí)例化一個(gè)對(duì)象,比如我們使用下面的代碼去實(shí)例化一個(gè)string的對(duì)象 
string str;同樣的我們的模板也是有實(shí)例化的一個(gè)過(guò)程的,就是在我們調(diào)用我們函數(shù)的時(shí)候,根據(jù)我們的參數(shù)進(jìn)行一個(gè)推演,比如剛剛的那個(gè)Add(x,y);這個(gè) 時(shí)候編譯器會(huì)根據(jù)參數(shù)的類(lèi)型,實(shí)例化生成一個(gè)參數(shù)是整形的Add函數(shù),然后在對(duì)他進(jìn)行一個(gè)調(diào)用,這個(gè)就是簡(jiǎn)單的實(shí)例化的過(guò)程。
所以說(shuō)上面的兩次調(diào)用實(shí)際上是生成了不同的函數(shù),然后進(jìn)行的一個(gè)調(diào)用的過(guò)程
小問(wèn)題
問(wèn)題一:模板函數(shù)和實(shí)例函數(shù)共存
還是上面Add函數(shù),如果我們這個(gè)時(shí)候在上面的模板函數(shù)的基礎(chǔ)之上又實(shí)現(xiàn)了一個(gè)函數(shù),這個(gè)時(shí)候會(huì)如何調(diào)用呢
int Add(const int& a,const int& b)
{return a+b;
}在這種情況下,如果我們有已經(jīng)實(shí)例化的函數(shù),這個(gè)時(shí)候會(huì)直接調(diào)用我們已經(jīng)實(shí)例化的函數(shù),如果沒(méi)有已經(jīng) 實(shí)例化的函數(shù),這個(gè)時(shí)候才會(huì)去找我們的模板函數(shù),然后實(shí)例化一個(gè)函數(shù)進(jìn)行一個(gè)調(diào)用的過(guò)程
問(wèn)題二:模板函數(shù)和實(shí)例函數(shù)參數(shù)不匹配
還是上面的程序,我們即有了一個(gè)模板函數(shù),又有了一個(gè)實(shí)例函數(shù),這個(gè)時(shí)候我們?cè)谑褂玫臅r(shí)候,傳遞的參數(shù)不是兩個(gè)整形而是兩個(gè)雙精度浮點(diǎn)型,那么這個(gè)時(shí)候是如何調(diào)用的呢
double a = 1.0;
double b = 2.0;
Add(a,b);這個(gè)時(shí)候會(huì)檢查我們的實(shí)例函數(shù),但是參數(shù)的類(lèi)型不匹配,所以實(shí)際上是生成了一個(gè)參數(shù)是double類(lèi)型的模板函數(shù),然后再進(jìn)行函數(shù)的一個(gè)調(diào)用的過(guò)程
如果我們的參數(shù)一個(gè)是int,一個(gè)是double的,這個(gè)時(shí)候又是怎么樣的呢,由大家自己去驗(yàn)證吧
這里我們還需要注意的一個(gè)問(wèn)題就是,實(shí)例化函數(shù)中的第二個(gè)參數(shù)不是一個(gè)const的時(shí)候,這個(gè)時(shí)候,我們的給 我們的參數(shù)傳入的是一個(gè)double的變量的時(shí)候,會(huì)發(fā)生隱式類(lèi)型的轉(zhuǎn)換的,這個(gè)時(shí)候會(huì)生成一個(gè)臨時(shí)的變量,這個(gè)臨時(shí)的變量具有常性,所以我們應(yīng)該在參數(shù)上面加上一個(gè)const
問(wèn)題三:模板實(shí)例化和類(lèi)型檢查
我們知道我們的模板函數(shù)只有在實(shí)例化的時(shí)候,才會(huì)生成可執(zhí)行代碼的,如果我們?cè)赩S下面測(cè)試的時(shí)候,編譯器是不會(huì)對(duì)模板函數(shù)的內(nèi)部進(jìn)行檢查的,比如我們少寫(xiě)了一個(gè)分號(hào),但是在linux下面使用g++進(jìn)行 編譯的時(shí)候是會(huì)進(jìn)行一個(gè)檢查的過(guò)程的
模板類(lèi)
模板類(lèi)也很容易實(shí)現(xiàn),只不過(guò)在使用的時(shí)候,我們需要對(duì)模板類(lèi)進(jìn)行一個(gè)顯式的實(shí)例化的過(guò)程
template<class T>
class Arr
{public:Str():_a(a){}private:T _a;
}Arr<int> arr;上面的調(diào)用就是一個(gè)顯式的實(shí)例化的過(guò)程
總結(jié)
以上是生活随笔為你收集整理的模板1.0 -- 模板基本原理的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
 
                            
                        - 上一篇: 《UNIX高级环境编程》 -- apue
- 下一篇: 开淘宝天猫店要多少钱?怎么开
