1. 程式人生 > 其它 >C++模板的宣告和定義為什麼不能分寫在.h與.cpp檔案中

C++模板的宣告和定義為什麼不能分寫在.h與.cpp檔案中

一般情況下,編寫一個類一般將標頭檔案(.h檔案)和原始檔(.cpp檔案)進行分離。.h檔案定義類和函式,.cpp檔案中進行函式的實現, 然後提供給其他.cpp檔案呼叫。但是在使用模板時,這種習慣性做法將變得不再有用,因為當例項化一個模板時,編譯器必須看到模板確切的定義,而不僅僅是它的宣告

模板定義很特殊,由template<…>處理的任何東西都意味著編譯器在當時不為它分配儲存空間(沒有具體的函式時不會對模板例項化),它一直處於等待狀態直到被一個模板例項告知。在編譯器和聯結器的某一處,有一機制能去掉指定模板的多重定義。所以為了容易使用,幾乎總是在標頭檔案中放置全部的模板宣告和定義。

由於C++是獨立編譯,例如a.cpp、b.cpp、c.cpp三個檔案,先獨立編譯成三個獨立的目標檔案,即a.o、b.o、c.o,然後再通過連結器連結起來,生成可執行檔案。

在編譯時,a.cpp發現一個函式呼叫,在當前檔案找不到函式定義,則在函式位置生成符號,在連結時,再尋找這個函式。

模板類是兩次編譯。第一次編譯時只對模板進行編譯,不生成具體函式,在呼叫時才生成具體函式。為什麼不能在第一次編譯就生成具體函式呢?請看下圖(取自vector模板原始碼迭代器“+”的定義和宣告):

標準要求編譯器(VS、GCC)在例項化模板時必須在上下文中可以檢視到其定義實體;而反過來,在看到例項化模板之前,編譯器對模板的定義體是不處理的——原因很簡單,編譯器怎麼會預先知道“typename 實參是什麼型別呢?”

因此模板的例項化與定義體必須放到同一翻譯單元中。

所以,最好的辦法就是將模板的宣告和定義都放置在同一個.h檔案中。這同時也是為什麼所有的STL標頭檔案都包含模板定義的原因。

本文來自部落格園,作者:Jcpeng_std,轉載請註明原文連結:https://www.cnblogs.com/JCpeng/p/15072692.html