在VS中新建TheC++StandardLibrary項目,在test測試tie的功能,將測試函數聲明在test.h文件,實現放到test.cpp文件,編譯時提示錯誤:
fatal error LNK1120: 1 個無法解析的外部命令
百度時才注意到,這是一個模板分離編譯問題,知乎上的回答:
鏈接:https://www.zhihu.com/question/20630104/answer/15722407
來源:知乎
來源:知乎
這個問題讓我想起我在實習的時候犯的一個錯誤,就是把模版類的定義和實現分開寫了,結果編譯出錯,查了兩天才查出問題。
C++中每一個對象所占用的空間大小,是在編譯的時候就確定的,在模板類沒有真正的被使用之前,編譯器是無法知道,模板類中使用模板類型的對象的所占用的空間的大小的。只有模板被真正使用的時候,編譯器才知道,模板套用的是什么類型,應該分配多少空間。這也就是模板類為什么只是稱之為模板,而不是泛型的緣故。
既然是在編譯的時候,根據套用的不同類型進行編譯,那么,套用不同類型的模板類實際上就是兩個不同的類型,也就是說,stack<int>和stack<char>是兩個不同的數據類型,他們共同的成員函數也不是同一個函數,只不過具有相似的功能罷了。
C++中每一個對象所占用的空間大小,是在編譯的時候就確定的,在模板類沒有真正的被使用之前,編譯器是無法知道,模板類中使用模板類型的對象的所占用的空間的大小的。只有模板被真正使用的時候,編譯器才知道,模板套用的是什么類型,應該分配多少空間。這也就是模板類為什么只是稱之為模板,而不是泛型的緣故。
既然是在編譯的時候,根據套用的不同類型進行編譯,那么,套用不同類型的模板類實際上就是兩個不同的類型,也就是說,stack<int>和stack<char>是兩個不同的數據類型,他們共同的成員函數也不是同一個函數,只不過具有相似的功能罷了。
如上圖所示,很簡短的六行代碼,用的是STL里面的stack,stack<int>和stack<char>的默認構造函數和push函數的入口地址是不一樣的,而不同的stack<int>對象相同的函數入口地址是一樣的,這個也反映了模板類在套用不同類型以后,會被編譯出不同代碼的現象。
所以 模板類的實現,脫離具體的使用,是無法單獨的編譯的;把聲明和實現分開的做法也是不可取的,必須把實現全部寫在頭文件里面。為了清晰,實現可以不寫在class后面的花括號里面,可以寫在class的外面。
所以 模板類的實現,脫離具體的使用,是無法單獨的編譯的;把聲明和實現分開的做法也是不可取的,必須把實現全部寫在頭文件里面。為了清晰,實現可以不寫在class后面的花括號里面,可以寫在class的外面。
在另一篇日志看到說,可以在類的定義源文件中使用關鍵字export,然后其他文件使用時只需包含類的定義頭文件就可以使用了,可以測試一下。