C++的模板爲什麼要在頭文件(.h)中實現?

今天是個科普文:C++的模板爲什麼要在頭文件(.h)中實現?

模板的用途

這個事情其實我沒什麼發言權,實話實說,我寫模板比較少。對於模板的重要性,也是最近才感覺到。至於模板的重要性,這裏也不多說,自己悟。


模板編寫

這裏就舉個函數模板的例子(我們把實現放在.cpp的錯誤例子):

lp_max.h



template <typename T>

T max(const T a, const T  b);




lp_max.cpp



template <typename T>

T max(const T a, const T  b)

{

if (a >= b) return a;

else return b;}




main.cpp



#include "lp_max.h"

using namespace std;

int main()

{

       cout << max(1, 2) << endl;

       cout << max('d','b' ) << endl;

       cout << max(1.5, 2.5) << endl;

     return 0;

}



例子很簡單,不要嫌棄,我們主要講道理。


編譯器處理

有些基礎知識的coder都知道,C/C++都是先編譯(compile)、再鏈接(link)(嚴格來說,編譯過程還可以細分,但是與本次說說明問題無關),模板方法的特化過程其實是在編譯(compile)階段完成的,也就是說在編譯過程中,模板被示例爲幾個實際的方法或者類就已經確定了。

鏈接(link)的時候,只會將compile階段生成的目標文件(.o .obj)鏈接起來,生成可執行程序。



回到我們剛纔的例子,我們實現了lp_max.h和lp_max.cpp,然後增加一個main方法去使用,編譯過程如下:


lp_max.cpp的編譯過程是模板方法的特化過程,這個過程會根據其他文件的引入情況去形成對應的函數實現,但是,由於沒有文件引入lp_max.cpp,造成的結果就是,lp_max.cpp看似很正常的編譯成lp_max.o目標文件,實際上,這個文件裏面什麼也沒有,是個空文件。


main.cpp編譯的時候,因爲頭文件引入了lp_max.h,知道有一個函數方法,但是,因爲頭文件中沒有實現,編譯器就假定其他地方會實現可用的方法,於是,標記出main.o需要幾個max方法,並且也編譯通過,等待連接時候,得到需要的max方法實現。


等到真正鏈接的時候,不幸的事情發生了,main.o在生成可執行文件時,找不到max方法的實現,這時候就會出現類似於下面的鬼東西(linux情況類似undefined reference to xxxx):



這時候,問題就暴露出來了,簡單的像一般函數一樣,頭文件.h聲明,.cpp文件實現出現了問題。如果你把模板方法的聲明、實現都放在頭文件lp_max.h,則在編譯出main.o的時候,就會按照需要生成不同的max()方法。


模板必須在頭文件中實現嗎?


很顯然不是,有一些方法可以將實現抽離出來。但是,從本質上來說,必須保證在編譯的時候,將需要的方法特化出來,才能夠正常通過鏈接。至於抽離的方法,有機會再分享。

本文的公衆號地址爲:C++的模板爲什麼要在頭文件(.h)中實現?,如果有幫助,關注一下。


·END·


有技術,有雞湯,還有碎碎念,盡在






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