2011-04-10 69 views
24

,所以我聽說C++模板不應該被分離成的.h和.cpp ...C++模板和頭文件

例如這樣的一個模板:

template <class T> 
class J{ 

    T something; 

} 

這是真的?爲什麼這樣?

如果因爲這個,我將不得不將兩個聲明和實現放在同一個文件中,我應該把它放在.h文件還是一個.cpp文件中?

+0

的答案在C++常見問題存在:http://www.parashift.com/c++-faq-lite/templates.html#faq-35.12 – birryree 2011-04-10 15:41:10

回答

23

標題。

這是因爲模板在編​​譯時被實例化,而不是鏈接時和不同的翻譯單元(大致相當於你的文件)只在鏈接時彼此「知道」。在編譯時,標題往往會被廣泛「認識」,因爲它們在任何需要它們的翻譯單元中。

閱讀https://isocpp.org/wiki/faq/templates瞭解更多。

2

如果您需要模板代碼可以被其他翻譯單元(.cpp文件)使用,您需要將實現放在.h文件中,否則這些其他單元將無法實例化模板(展開它根據他們使用的類型)。

如果您的模板函數僅在一個.cpp文件中實例化,您可以在其中定義它。有時候,當一個類有一個私有成員函數,它是一個模板(並且它只從實現文件中調用,而不是類頭文件)時會發生這種情況。

4

是的,的確如此。聲明和實現通常放在頭文件中。一些編譯器嘗試使用export關鍵字來允許它們分離,但已從C++ 0x中刪除。查看this FAQ entry瞭解所有骯髒的細節。

12

您無法將模板類放入.cpp文件的原因是,爲了「編譯」.cpp文件,您需要知道用什麼類型來代替T.因爲它符合一個模板化的類(比如你的J類)沒有足夠的信息進行編譯。因此它必須全部在標題中。

如果您希望將實現分解爲另一個文件以保持清潔,最佳做法是使用.hxx文件。是這樣的:你的頭文件中,JH,提出:

#ifndef _J_H__ 
#define _J_H__ 

template <class T> class J{ // member definitions }; 

#include "j.hxx" 

#endif // _J_H__ 

,然後在j.hxx你必須

template <class T> J<T>::J() { // constructor implementation } 

template <class T> J<T>::~J() { // destructor implementation } 

template <class T> void J<T>::memberFunc() { // memberFunc implementation } 

// etc. 

最後在你的.cpp文件使用的模板類,讓我們稱它爲K.cpp你必須:

#include "J.h" // note that this always automatically includes J.hxx  
void f(void) 
{ 
    J<double> jinstance; // now the compiler knows what the exact type is. 
} 
+2

我m不知道使用'.hpp'擴展名。按照慣例,在C++中'.h'和'.hpp'幾乎是可以互換的,所以你不用'j.hpp'來填充'j.hpp',它的文件名與'J.h'的功能區別。 [這裏的約定是'J.hxx'。](http://bytes.com/topic/c/answers/132004-inline-template-file-extensions) – 2011-10-26 00:43:28

+0

+1好點,我一直使用.hxx在實踐中也是如此(主要是通過別人的例子來學習),但是我從來不明白爲什麼直到現在它纔是正確的。 – 2011-10-26 01:13:27

+0

如果我可能會問,這有什麼用?最後,如果.h *或*,則重新編譯每個#including .cpp文件。hxx文件被修改;並修改它在.h中的實現(不是這個例子;我的意思是當整個模板在.h中)應該幾乎相同,機械地,不是? – Noein 2015-03-30 19:39:52