C/C++編程筆記:C++模板詳解(一)函數(shù)模板的概念和特性
函數(shù)模板是指這樣的一類函數(shù):可以用多種不同數(shù)據(jù)類型的參數(shù)進(jìn)行調(diào)用,代表了一個函數(shù)家族。它的外表和普通的函數(shù)很相似,唯一的區(qū)別就是:函數(shù)中的有些元素是未確定的,這些元素將在使用的時候才被實例化。

先來看一個簡單的例子:
一、定義一個簡單的函數(shù)模板
下面的這個例子就定義了一個模板函數(shù),它會返回兩個參數(shù)中最大的那一個:

這個函數(shù)模板定義了一個“返回兩個值中最大者”的函數(shù)家族,而參數(shù)的類型還沒有確定,用類型模板參數(shù)T來確定。模板參數(shù)需要使用如下的方式來聲明:
template< 模板參數(shù)列表 >
在這個例子中,模板參數(shù)列表為:typename T。關(guān)鍵字typename引入了T這個類型模板參數(shù)。當(dāng)然了,可以使用任何標(biāo)識符作為類型模板參數(shù)的名稱。我們可以使用任何類型(基本數(shù)據(jù)類型、類類型)來實例化該函數(shù)模板,只要所使用的數(shù)據(jù)類型提供了函數(shù)模板中所需要的操作即可。例如,在這個例子中,類型T需要支持operator <,因為a和b就是通過這個操作符來比較大小的。
鑒于歷史原因,也可以使用關(guān)鍵字class來取代typename來定義類型模板參數(shù),然而應(yīng)該盡可能地使用typename。
二、使用函數(shù)模板
下面的程序使用了上面定義的這個函數(shù)模板:

通常而言,并不是把模板編譯成一個可以處理任何類型的單一實體,而是針對于實例化函數(shù)模板參數(shù)的每種類型,都從函數(shù)模板中產(chǎn)生出一個獨立的函數(shù)實體。因此,針對于每種類型,模板代碼都被編譯了一次。這種用具體類型代替模板參數(shù)的過程,叫做模板的實例化。它產(chǎn)生了一個新的函數(shù)實例(與面向?qū)ο蟪绦蛟O(shè)計中的實例化不同)。
如果試圖基于一個不支持模板內(nèi)部所使用的操作的類型實例化一個模板,那么將會引發(fā)一個編譯期錯誤:

所以說:模板被編譯了兩次,分別發(fā)生于:
模板實例化之前,查看語法是否正確,此時可能會發(fā)現(xiàn)遺漏的分號等。
模板實例化期間,檢查模板代碼, 查看是否所有的調(diào)用都有效。此時可能會發(fā)現(xiàn)無效的調(diào)用,例如實例化類型不支持某些函數(shù)調(diào)用等。
所以這引發(fā)了一個重要的問題:當(dāng)使用函數(shù)模板并且引發(fā)模板實例化時,編譯器必須查看模板的定義。事實上,這就不同于普通的函數(shù),因為對于普通的函數(shù)而言,只要有函數(shù)的聲明(甚至不需要定義),就可以順利地通過編譯期。
三、函數(shù)模板實參推斷
當(dāng)我們?yōu)槟承崊⒄{(diào)用一個函數(shù)模板時,模板參數(shù)可以由我們所傳遞的實參來決定。
注意:函數(shù)模板在推斷參數(shù)類型時,不允許自動類型轉(zhuǎn)換,每個類型模板參數(shù)都必須正確的匹配。

注意:模板實參推斷并不適合返回類型。因為返回類型并不會出現(xiàn)在函數(shù)調(diào)用參數(shù)的類型里面。
所以,必須要顯示地指定返回類型:

四、函數(shù)模板的重載
和普通的函數(shù)一樣,函數(shù)模板也可以被重載。在下面的例子中,一個非模板函數(shù)可以和一個同名的函數(shù)模板同時存在,這稱為函數(shù)模板的特化。而且該函數(shù)模板還被實例化為這個非模板函數(shù)。

總結(jié)如下:
(1)對于非模板函數(shù)和同名的函數(shù)模板,如果其它條件都是相同的話,那么在調(diào)用的時候,重載解析過程中會優(yōu)先調(diào)用非模板函數(shù),而不會實例化模板(04)。
(2)如果模板可以產(chǎn)生一個具有更好匹配的函數(shù),那么將選擇模板(02, 03)。
(3)還可以顯示地指定一個空的模板參數(shù)列表,告訴編譯器:必須使用模板來匹配(05)。
(4)由于函數(shù)模板拒絕隱式類型轉(zhuǎn)換,所以當(dāng)所有的模板都無法匹配,但是發(fā)現(xiàn)可以通過強(qiáng)制類型轉(zhuǎn)換來匹配一個非模板函數(shù)時,將調(diào)用那個函數(shù)(07)。
五、函數(shù)模板重載的注意事項
在重載函數(shù)模板時,請謹(jǐn)記:將對函數(shù)聲明的改變限制在以下兩種情況中:
改變參數(shù)的數(shù)目
顯示指定模板的參數(shù)(即函數(shù)模板特化)
否則,很可能會導(dǎo)致非預(yù)期的結(jié)果,例如在下面的例子中,模板函數(shù)是使用引用進(jìn)行傳參的,然而在其中的一個重載中(實際上是針對char*進(jìn)行的特化),卻使用了值傳遞的方式,這將會導(dǎo)致不可預(yù)期的結(jié)果:

博客園:https://www.cnblogs.com/rosefinch/p/12294338.html

學(xué)習(xí)C/C++編程知識,歡迎關(guān)注UP,更多C/C++編程知識持續(xù)更新~