1. 程式人生 > >童話故事 --- 類模板與函數模板的實例化

童話故事 --- 類模板與函數模板的實例化

程序 無聊 鏈接 函數 奇怪 com border primer 調用方法

摘要:函數模板的實例化,類模板的實例化,類模板和函數模板的實例化的比較

高飛狗:

Hi,黛絲!好久不見,最近可好?

黛絲:

你就別提了,煩得要死!

高飛狗:

有什麽煩心事,跟我說說,看我能不幫你排憂解難?

黛絲:

歷經千辛萬苦,1個月內學習強國已經突破1000點大關。

高飛狗:

進步神速呀!

黛絲:

跟自己比,進步神速;可是跟別人比,落後得更神速!你說奇怪不奇怪?

高飛狗:

真夠奇真夠怪的!

黛絲:

高飛,你不會沒事閑得無聊專程來聽我訴苦的吧?

我知道你無事不登八寶殿,有什麽事你就直說。

高飛狗:

還是黛姐姐您最善解人意哪!

我最近學習也變得非常刻苦,正在研究函數模板和類模板,什麽顯示explicit實例化,什麽隱式implicit實例化,越學越暈,您能給講解講解嗎?

黛絲:

你什麽時候也變得勤奮好學起來了?

看你態度這麽真誠,我就把我知道的都抖落給你吧。

黛絲:

先說函數模板的實例化。

函數模板實例化的方法有兩種:隱式實例化和顯式(明確)實例化。

隱式實例化:應用程序調用了一個既未聲明又未定義的函數。編譯器就到函數模板庫中查找同名函數模板,根據被調用函數的入口參數和返回值,確定相匹配的函數模板,並生成一個函數實例。隱式的意思就是應用程序未明確聲明或定義函數實例。

顯式(明確)實例化:應用程序明確聲明並定義了一個函數模板的實例,如下表所示。

// 定義一個函數模板,返回兩個數的小者

template <typename T>

T min(const T & a, const T & b)

{

return (a < b) ? a : b;

}

顯式(明確)實例化

template int min <int> (const int & a, const int & b);

編譯器遇到顯式(明確)實例化語句,立即產生一個相應的函數實例

函數模板顯式(明確)實例化的寫法

正確寫法

尖括號部分是關鍵,C++ Primer V6書中的如下寫法是正確的:

template int min <int> (const int & a, const int & b);

錯誤寫法

C++ Primer V5書中的如下寫法是錯誤的:

template int min (const int & a, const int & b);

函數模板顯式(明確)實例化後的調用方法

正確寫法

尖括號部分是關鍵:

int c = min <int> (a, b);

錯誤寫法

沒有尖括號部分是錯誤的

int c = min (a, b);

取得顯式(明確)實例化函數的地址或指針

正確寫法

尖括號部分是關鍵,函數名稱就是函數地址。函數實例的名稱必須包括類型信息

auto fp = min <int>; 或者auto fp = &min <int>;

錯誤寫法

沒有尖括號部分是錯誤的

auto fp = min; 或者auto fp = &min;

函數實例的定義和聲明

函數實例的定義和聲明方法

定義寫法

template int min <int> (const int & a, const int & b);

聲明寫法

關鍵字extern 表示聲明而非定義

extern template int min <int> (const int & a, const int & b);

編譯器見到函數實例的定義,就產生一個函數實例。

編譯器見到函數實例的聲明,就知道了調用這個函數實例的方式,也知道這個函數已在其它地方被定義,不必產生再一個函數實例。

再來說類模板的實例化。

類模板只有顯式(明確)實例化,無法隱式實例化。比較簡單,不再累述。

把類模板和函數模板的實例化做個對比,如下圖所示:

技術分享圖片

情形

編譯器行為

隱式實例化函數模板

一定將實例代碼鏈接進入可執行程序中,因為函數實例肯定被調用了。

顯式實例化函數模板,但未被應用程序調用

實例代碼不會被鏈接進入可執行程序中。因為未被調用,將其鏈接進入可執行程序中沒有用。

就如同我們定義了一個普通函數,但未被任何其它函數調用,其代碼不會被鏈接進入可執行程序中。

顯式實例化函數模板,且被應用程序調用

一定將實例代碼鏈接進入可執行程序中

實例化類模板,但應用程序未定義相應的對象

實例代碼不會被鏈接進入可執行程序中。因為未定義相應的對象,將其鏈接進入可執行程序中沒有用。

就如同我們定義了一個普通類,但未定義相應的對象,其代碼不會被鏈接進可執行程序中。

實例化類模板,且應用程序定義了相應的對象

一定將實例代碼鏈接進入可執行程序中

另外,要重點提醒的是,尤其是在MCU上開發C++應用的朋友要註意:若類的對象是局部對象或全局對象,其生命周期貫穿整個應用程序,且其構造函數在main()函數之前被調用執行,所以這些對象的構造函數不可做太多工作。

高飛:

親愛的,你講得太清楚了,讀書效率太低下,讀你以分鐘勝讀十年書!

黛絲:

好你個油嘴滑舌!你說要給我排憂解難的,折騰半天,誰給誰排除萬難了?

童話故事 --- 類模板與函數模板的實例化