1
"Times New Roman";mso-hansi-font-family:"Times New Roman"'>函數模板mso-bidi-font-family:Arial">1.1 初探函數模板
mso-hansi-font-family:"Times New Roman"'>函數模板的定義
mso-pattern:gray-15 auto">templates<comma-separated-list-of-parameters>
….
Wingdings;mso-fareast-font-family:Wingdings;mso-bidi-font-family:Wingdings">l
"Times New Roman";mso-hansi-font-family:"Times New Roman"'>模板函數會進行實參演繹,所以在使用函數模板的時候,一般不需要制定參數的類型。
Wingdings;mso-fareast-font-family:Wingdings;mso-bidi-font-family:Wingdings">l
"Times New Roman";mso-hansi-font-family:"Times New Roman"'>就編譯原理來說,並不是把模板編譯成一個可以處理任何類型的單一實體,而是對於執行個體化模板參數的每種類型,都從模板產生出一個不同的實體。
Wingdings;mso-fareast-font-family:Wingdings;mso-bidi-font-family:Wingdings">l
"Times New Roman";mso-hansi-font-family:"Times New Roman"'>如果試圖基於一個不支援模板內部所使用的操作的類型執行個體化一個模板,那麼將會導致一個編譯期錯誤,由此,我們可以得出結論:模板被編譯了兩次:
Wingdings;mso-fareast-font-family:Wingdings;mso-bidi-font-family:Wingdings">n
"Times New Roman";mso-hansi-font-family:"Times New Roman"'>執行個體化之前,先檢查模板代碼本身,看文法是否正確;
Wingdings;mso-fareast-font-family:Wingdings;mso-bidi-font-family:Wingdings">n
"Times New Roman";mso-hansi-font-family:"Times New Roman"'>在執行個體化期間,檢查模板代碼,查看是否所有的模板都有效。
Wingdings;mso-fareast-font-family:Wingdings;mso-bidi-font-family:Wingdings">l
"Times New Roman";mso-hansi-font-family:"Times New Roman"'>由於上面提到的,模板要被執行個體化,所以在編譯的時候,編譯期就需要知道模板的定義。這就不同於普通函數中編譯和連結之間的區別,因為對於普通函數而言,只要有函數的聲明就可以編譯通過,但是模板函數不行,為此,一般來說,模板函數都採用內嵌函式的方式。
mso-bidi-font-family:Arial">1.2 模板參數
mso-hansi-font-family:"Times New Roman"'>這裡要明白兩個概念:
Wingdings;mso-fareast-font-family:Wingdings;mso-bidi-font-family:Wingdings">l
"Times New Roman";mso-hansi-font-family:"Times New Roman"'>模板參數,位於角括弧內;
Wingdings;mso-fareast-font-family:Wingdings;mso-bidi-font-family:Wingdings">l
"Times New Roman";mso-hansi-font-family:"Times New Roman"'>調用參數,位於圓括弧內;
mso-pattern:gray-15 auto">template<typename T1, typename T2>
mso-pattern:gray-15 auto">inline T1 max(T1
const& a, T2 const&)
mso-pattern:gray-15 auto">{
mso-pattern:gray-15 auto"> return
a<b? b:a;
mso-pattern:gray-15 auto">}
mso-ascii-font-family:"Times New Roman";mso-hansi-font-family:"Times New Roman"'>注意上面的函數的傳回值為T1mso-hansi-font-family:"Times New Roman"'>,而不是T1
const&mso-hansi-font-family:"Times New Roman"'>,此處必須是T1"Times New Roman"'>,因為在將T2 const&"Times New Roman"'>轉型為T1宋體;mso-ascii-font-family:"Times New Roman";mso-hansi-font-family:"Times New Roman"'>的過程中會產生一個局部變數,而局部變數是不能作為引用返回的。
mso-ascii-font-family:"Times New Roman";mso-hansi-font-family:"Times New Roman"'>如果有多個模板參數,你可以只顯式指定第一個實參,而讓演繹過程推匯出其餘的參數。通常來說,你必須指定“最後一個不能被演繹的模板實參之前的”所有實參類型。
mso-hansi-font-family:"Times New Roman"'>例如:
mso-pattern:gray-15 auto">Template<typename RT, typename T1, typename T2>
mso-pattern:gray-15 auto">Inline RT max(T1 const& a, T2 const& b)
mso-pattern:gray-15 auto">{
mso-pattern:gray-15 auto"> return a<b?
b:a;
mso-pattern:gray-15 auto">}
mso-bidi-font-family:Arial">1.3 重載模板函數
mso-ascii-font-family:"Times New Roman";mso-hansi-font-family:"Times New Roman"'>首先,重載就是一個很難的話題,這裡頭有一些細節是一般人(包括我)所不瞭解的。要瞭解重載的細節,可以參考本書附錄。
mso-ascii-font-family:"Times New Roman";mso-hansi-font-family:"Times New Roman"'>我們來看個例子:
//(1)
Inline int
const& max(int const& a, int const& b)
{ return a <
b? b:a;}
//(2)
Template<typename
T>
Inline T
const& max(T const& a , T const& b)
{ return a <
b? b:a;}
//(3)
Template<typename
T>
Inline T
const& max(T const& a , T const& b, T const& c)
{ return
::max(max(a,b),c); }
Int main()
{
::max<>(7, 42); //"Times New Roman"'>調用2
::max(‘a’, 42.7); //"Times New Roman"'>調用1
}
Wingdings;mso-fareast-font-family:Wingdings;mso-bidi-font-family:Wingdings">l
"Times New Roman";mso-hansi-font-family:"Times New Roman"'>在其他函數都相同的情況下,在調用的時候,重載解析過程通常會調用非模板函數,而不會從該模板產生出一個執行個體。這站在編譯器的角度來看,也容易理解。因為如果再從模板執行個體化一個,則會使代碼變得更加龐大,而且產生重複。
Wingdings;mso-fareast-font-family:Wingdings;mso-bidi-font-family:Wingdings">l
"Times New Roman";mso-hansi-font-family:"Times New Roman"'>模板是不允許進行自動類型轉換的,所以上面的第二個調用將調用(1)mso-hansi-font-family:"Times New Roman"'>,而不是(2"Times New Roman"'>)。
Wingdings;mso-fareast-font-family:Wingdings;mso-bidi-font-family:Wingdings">l
"Times New Roman";mso-hansi-font-family:"Times New Roman"'>一般來說,在重載函數模板的時候,最好只改變那些需要改變的內容,也就是說,你應該吧你的改變限制在下面兩種情況:改變參數的數目,或者顯式的指定模板參數,否則可能導致一些非預期的行為,具體例子見本書p18.
Wingdings;mso-fareast-font-family:Wingdings;mso-bidi-font-family:Wingdings">l
"Times New Roman";mso-hansi-font-family:"Times New Roman"'>函數的所有重載版本的聲明應該位於該函數被調用的位置之前。