C++深入理解(4)------函數模板以及顯式具體化(讀書筆記)

    在編程的過程中雖然很少使用到函數模板,但是在底層代碼的編寫中卻有時會用到,下面將詳細介紹一下函數模板:

    函數模板是一種應用泛型的一種方式,可以定義一個函數,函數的參數和返回值都是可以根據模板而變動的,不用定義多個重載函數來實現因爲參數不同而功能相同的問題。

    如下面的交換函數,void swap(int &a,int &b){}; 有時候我們會用到int類型,有時候會用到double類型,功能相同的函數卻因爲參數不同卻要重新編寫一次,不僅浪費時間,而且非常容易出錯,所以使用函數模板就可以避免這種問題。

    下面寫出模板定義的標準格式
    template <typename T>void swap(T &a,T &b){}或者

    template<class T> void swap(T &a,T &b);

    這裏簡單的說下tpyename和class的異同:他們兩個在作用上是相同的,都是表示模板類型的關鍵詞,兩者在使用上沒有任何區別,唯一的區別在與typename可以更清晰的告訴讀者是模板類型,而class更繞一點,但是有大量的庫使用class這種用法的。

    本質上說:模板並不創建任何函數,而是類似一個過程語言,它來告訴編譯器怎麼去創建一個函數,如需要用int來替換時,就會用int來創建一個函數,而需要用double來替換時,就用double來創建一個函數。因此函數模板並不能縮短函數執行過程, 在執行時仍然需要創建兩個函數定義,而最終的代碼是不包含任何模板的,只包含模板生成的實際函數。所以使用模板的好處是可以減少手工定義的工作量。

    這裏額外還要說的一個概念是顯式具體化,有時候定義的模板能處理大部分的類型,但是有某些特殊類型需要卻與基本的算法不同,這時就要用到顯式具體化這種神奇的東西:

    其標準的格式是:

    template <> void swap<job>(job &a,job &b){.......};

    這樣可以定義複雜的結構job,當調用以job作爲參數的函數時,就優先調用這個顯示具體化的函數,如果沒有job作爲參數的顯式具體化,那麼還是根據老的模板來定義job函數。

    這裏需要另外說明的還有一個概念:顯式實例化。這個概念比較和顯示具體化是兩個不同的概念。顯示實例化的標準格式 template void swap<int>(int &a,int &b);

    通過使用顯示實例化這樣聲明,編譯器就知道要穿件一個int類型的函數定義,與之對應的是隱式實例化,只有當遇到swap(a,b),a,b都爲int類型時纔會創建這個函數定義。而顯示實例化卻是要穿件另外一種類型的不同算法,前者(顯示實例化)是不改變算法只創建函數,而後者則是即改變算法也創建。

    概念基本講完了,說下使用中注意的細節,在使用中常常會遇到這樣的問題:

    swap(T1 &a, T2 &b){    ...   ?type? = a + b; ...} 那麼a+b是什麼類型呢,因爲a可能是int,b可能是double,則a+b爲double,其他傳入類型又是不同的,這裏C++增加了一個關鍵詞decltype,具體使用爲decltype(a+b) c=a+b;decltype() 後聲明的變量c爲與()內部的變量是同一種類型的變量。

    還有一種返回值也是不知道type的,如?type? swap(T a,T b);返回值也是不定的,這裏可以使用C++新的後置返回類型,具體的格式如下:

    template <class T1,class T2>

    auto func(T1 x,T2)->decltpye(x+y){}

    其中的->表示返回值類型爲->後類型相同的類型。


    



發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章