在我們做c++開發的過程中,通常我們寫乙個類就會有乙個.h和.cpp檔案,當我們需要呼叫乙個函式或者引用乙個變數時我們只需要包含宣告這些函式或者變數的.h檔案即可,
當我們編譯c++專案時,每個cpp檔案被編譯成乙個.obj檔案,在這些.obj檔案只包含非本檔案函式的宣告而沒有這些函式的二進位制**,當我們呼叫這些函式時會生成乙個call指令去呼叫函式,當在自己的.obj檔案裡找不到關於該函式的二進位制檔案時,編譯器會交給c++聯結器linker,此時linker會在其他.obj檔案裡尋找關於這些函式真正的定義找到相關的二進位制**,然後執行該函式。
這樣做有它的好處,首先我們乙個專案不可能都寫在乙個檔案裡,這樣有利於專案模組的劃分,其次有利於我們快速的定位專案中的錯誤。
但是當分離式編譯碰到c++模版的時候就不靈了,要知道模版在例項化之前是不會被編譯成二進位制的,當我們有乙個c++模版類的時候,此類在例項化之前是不會被編譯成二進位制**的,而且對於模版類的函式,如果我們沒有在它所在的.obj檔案裡被呼叫是不會被例項化的,也就是說這些函式不會生成相應的二進位制**的,此時如果我們呼叫這些函式c++編譯器就會給出我們最不願看到的編譯錯誤了。因此我們不得不把模版類的定義和宣告放在同個乙個檔案裡。如果我們非要分開呢。
下面我們看乙個模版例子
//
// header.h
// demo
//// created by 杜國超 on 17/2/15.
//#ifndef header_h
#define header_h
#include
#include
#define sixday_rank_num 10
template
class templateclassa
;template
class templateclassb
; class xrankuser ; #endif /* header_h */
//
// header.cpp
// demo
//// created by 杜國超 on 17/2/15.
//#include "../inc/header.h"
template
templateclassa
::templateclassa()
template
void templateclassa
::init(t id, int iscore)
template
void templateclassa
::reset() template
templateclassb
::templateclassb() template
templateclassb
::~templateclassb() template
void templateclassb
::reset() template
void templateclassb
::say() xrankuser::xrankuser() xrankuser::~xrankuser() void xrankuser::init() void xrankuser::scorerankssay()
#include
using namespace std;
#include "inc/header.h"
int main(int argc, const char * argv)
首先現在的**結構,模版的宣告和定義是分開的,並且是可以編譯通過的,但是要注意,如果我們注釋header.h檔案裡的標記1的**(注意此時用到此成員變數的地方也要相應注釋掉),main函式中的標記4處的**將會報錯,開啟注釋執行正常,因為標記1處的宣告導致了在建構函式中呼叫了相關模版的建構函式,此時建構函式被編譯,所以才編譯通過。同理如果我們去掉header.cpp中的標記1,那麼main函式的標記2會報錯,去掉header.cpp的標記2main函式的標記3會報錯,當然我們通常會通過main函式標記1代替標記3的**,這裡只是為了說明問題,可見在.cpp檔案中被呼叫過的函式是不受模版的影響的,這也就證明了在相應的.cpp檔案中沒有被呼叫的函式沒有背編譯進.obj檔案中。
因此我們在寫c++模版的時候兩種方式來避免分離式編譯對模版的影響,一是把宣告和定義放在同乙個檔案裡,二就是在模版所在的.obj檔案裡呼叫模版的函式,就像header標頭檔案和cpp檔案標記的**一樣。
C 不支援模版的分離式編譯
1 c 不支援模版的分離式編譯,為什麼?c 是分別,單獨編譯,對於每個cpp檔案,預編譯為編譯單元,這個編譯單元是自包含檔案,編譯的時候,不需要其他的檔案,編譯好了,生成obj檔案,然後連線成exe檔案。在編譯的時候,使用乙個東西,如果這個東西就在當前位置,當然好了。如果不再當前位置,也沒關係,只要...
為什麼模板不支援分離編譯?
在c 中,為了乙個專案的規範化我們通常把 歸類為三類 宣告檔案 實現檔案 測試檔案。比如,我們要實現乙個順序表,那麼規範化就是建立3個檔案 seqlist.h 順序表相關宣告 seqlist.cpp 順序表相關實現 test.cpp 順序表測試檔案 那麼普通順序表這樣寫一點問題都沒有,用模板實現成這...
為什麼模板不支援分離編譯
在c 中,為了乙個專案的規範,我們通常把 歸為三類 宣告檔案 實現檔案 測試檔案.比如,我要用c 實現乙個鍊錶,那麼就會建立這3個檔案 linklist.h 鍊錶的相關宣告 linklist.cpp 鍊錶的實現 test.cpp 鍊錶測試 本文忽略 那麼問題來了,普通鍊錶這樣寫起來一點問題都沒有 如...