c++中模板類的成員函式的宣告與定義應該放在標頭檔案裡

csu_zhengzy~發表於2018-11-14

今天嘗試自己實現vector資料結構底層,在定義vector模板類的時候,還想像往常一樣把類分為.h檔案和.cpp檔案,把成員函式的宣告放在.h檔案中,把具體實現放在.cpp檔案中,結果在測試時發現在編譯過程中報錯。除錯了很久,重視提示“無法解析的外部符號”,如圖所示:

                         

最終我找到了原因:

引用C++primer的話:C++支援兩種模板編譯模式包含模式Inclusion  Model  和分離模式Separation  Model  

1. 包含編譯模式  

在包含編譯模式下我們在每個模板被例項化的檔案中包含函式模板的定義並且往往把定義放在標頭檔案中像對行內函數所做的那樣 

2. 分離編譯模式    

在分離編譯模式下函式模板的宣告被放在標頭檔案中 ,  在模板定義中有一個關鍵字export,  關鍵字export  告訴編譯器在生成被其他檔案使用的函式模板例項時可能需要這個模板定義編譯器必須保證在生成這些例項時該模板定義是可見的 , 關鍵字export  不需要出現在標頭檔案的模板宣告中, 分離模式使我們能夠很好地將函式模板的介面同其實現分開進而組織好程式以便把函式模板的介面放到標頭檔案中而把實現放在文字檔案中, 但是並不是所有的編譯器都支援分離模式, 即使支援也未必總能支援得很好, 支援分離模式需要更復雜的程式設計環境所以它們不能在所有C++編譯器實現中提供.  

理解: 現在的VC++編譯器都不知道模板分離編譯模式,所以還是要把定義與實現都放在一個檔案中。

再回頭看上面的例子,可以知道建構函式也是一個模板,在main.cpp中建立一個vector要建立一個建構函式模板的例項 。例項化要素體現在main.cpp檔案中,如一些函式的實參(a,b,c)。如果按照傳統方式,編譯器在vector.h檔案中看到了模板的宣告,但沒有模板的定義,這樣編譯器就不能建立vector(a,b,c)。但這時並不出錯,因為編譯器認為模板定義在其它檔案中,就把問題留給連結程式處理。  現在,編譯vector.cpp時會發生什麼問題呢?編譯器可以解析模板定義並檢查語法,但不能生成成員函式的程式碼。它無法生成程式碼,因為要生成程式碼,需要知道模板引數,即需要一個型別,而不是模板本身。這樣,連結程式在main.cpp 或 vector.cpp中都找不到vector(a,b,c)的定義,於是報出無定義成員的錯誤。

相關文章