模板類成員函式的定義和宣告為什麼要放在一個檔案中

期待一片自己的藍天發表於2014-08-02

“通常情況下,你會在.h檔案中宣告函式和類,而將它們的定義放置在一個單獨的.cpp檔案中。但是在使用模板時,這種習慣性做法將變得不再有用,因為當例項化一個模板時,編譯器必須看到模板確切的定義,而不僅僅是它的宣告。因此,最好的辦法就是將模板的宣告和定義都放置在同一個.h檔案中。這就是為什麼所有的STL標頭檔案都包含模板定義的原因。”[1]

"標準要求編譯器在例項化模板時必須在上下文中可以檢視到其定義實體;而反過來,在看到例項化模板之前,編譯器對模板的定義體是不處理的——原因很簡單,編譯器怎麼會預先知道 typename 實參是什麼呢?因此模板的例項化與定義體必須放到同一翻譯單元中。"[1]


"《C++程式設計思想》第15章(第300頁)說明了原因:
模板定義很特殊。由template<…> 處理的任何東西都意味著編譯器在當時不為它分配儲存空間,它一直處於等待狀態直到被一個模板例項告知。在編譯器和聯結器的某一處,有一機制能去掉指定模板的多重定義。所以為了容易使用,幾乎總是在標頭檔案中放置全部的模板宣告和定義。
"[2]


"對C++編譯器而言,當呼叫函式的時候,編譯器只需要看到函式的宣告。當定義類型別的物件時,編譯器只需要知道類的定義,而不需要知道類的實現程式碼。因此,因該將類的定義和函式宣告放在標頭檔案中,而普通函式和類成員函式的定義放在原始檔中。
       但在處理模板函式和類别範本時,問題發生了變化。要進行例項化模板函式和類别範本,要求編譯器在例項化模板時必須在上下文中可以檢視到其定義實體;而反過來,在看到例項化模板之前,編譯器對模板的定義體是不處理的——原因很簡單,編譯器怎麼會預先知道 typename 實參是什麼呢?因此模板的例項化與定義體必須放到同一翻譯單元中。
"[3]



[1] 任何時候都適用的20個C++技巧. http://www.uml.org.cn/c++/20112284.asp 

[2] 為什麼不能將類别範本的宣告與類别範本函式實現分開寫. http://blog.sina.com.cn/s/blog_684355870100jmjr.html

[3]類别範本和模板函式連線出錯處理. http://www.cppblog.com/kenny/archive/2011/04/23/144841.html

[4]知乎上有一個能實現分開編譯的例子,但是很不人性化。。。http://www.zhihu.com/question/20630104


相關文章