2010-10-15 60 views
4

任何人都可以詳細說明原因?爲什麼聲明/定義必須都在C++模板類的源文件中?

+0

我剛剛意識到我沒有真正回答你的問題。但那只是因爲你說錯了。我知道你的意思,因爲我記得曾經有過同樣的問題,所以我對這個問題很熟悉。問題應該是「爲什麼聲明/定義必須都在C++模板類的頭文件中」?不幸的是,我沒有編輯問題的代表。 – 2010-10-15 07:58:56

+0

因此,在我的問題中'source'應該改爲'header',對吧? – tem 2010-10-15 08:02:37

+0

是的。在C++中,源文件是包含函數體(.cpp)的文件。標題是包含你的原型和你的類體(.h或.hpp)的標題。 – 2010-10-15 08:16:23

回答

3

源文件彼此獨立編譯爲可執行代碼,然後再鏈接到主程序。另一方面,模板函數不能在沒有模板參數的情況下編譯。因此,使用它們的文件需要有該代碼才能編譯。因此這些函數需要在頭文件中可見。

應許例如:

template<class T> 
void swap(T & a, T & b) 
{ 
    T temp = a; 
    a = b; 
    b = temp; 
} 

T類這裏的唯一的要求是,它有一個公共的賦值運算符(=)。這就是所有曾經實施或設想過的課程。但是,每個類都以自己的方式實現賦值運算符。不能爲交換生成相同的機器代碼<int>,交換<雙重>和交換<字符串>。這些功能中的每一個都必須是唯一的。同時,編譯器不可能預見到可能傳遞給該函數的所有不同類型,因此它不能提前生成函數。所以它必須等到函數被調用,然後它才能被編譯。

例如,假設我具有上面定義在「swap.h」中的那個函數。然後在「main.cpp」中,我這樣做:

int main() 
{ 
    int a=5, b=10; 
    double c=3.5, d=7.9; 
    string s1="hello"; 
    string s2="world"; 

    swap(a,b); 
    swap(c,d); 
    swap(s1,s2); 
} 

在此示例中,創建了3個不同的函數。一個交換ints,一個交換雙打,一個交換字符串。爲了創建這些函數,編譯器需要能夠看到模板代碼。如果它是在一個單獨的源文件中,例如「swap.cpp」,編譯器將無法看到它,因爲就像我之前所說的那樣,每個源文件都是相互獨立編譯的。

+0

爲什麼'模板函數不能在沒有模板參數的情況下編譯? – tem 2010-10-15 07:14:22

+0

@tem:因爲當您使用特定的一組模板參數調用模板函數時,該函數是唯一的。例如,如果我調用func (),則該函數的行爲與我調用func ()或func ()時的行爲不同。我會編輯我的答案並舉個例子。 – 2010-10-15 07:23:08

+0

很好,如果你能想出一個例子。 – tem 2010-10-15 07:25:52

2

你問爲什麼模板體必須在頭文件?這是因爲編譯器需要同時知道主體和模板參數以生成機器代碼。模板參數在使用模板(實例化)的位置是已知的。這給你一個平凡的例子和兩個非平凡的例子:

  1. (Trivial)該模板只在一個源文件中使用,所以正文可以在同一個源文件中。
  2. 使身體在每次使用時都可用,這通常意味着在頭文件中。
  3. 在包含正文的源文件中,顯式實例化每個需要的模板參數組合。
+1

我仍然不明白他們爲什麼不能在兩個文件? – tem 2010-10-15 06:34:28

+2

除非我錯誤地理解了它可能會發生的事情,但它需要知道正文,所以無論何時要使用該模板,都必須以正確的順序包含這兩個文件,這樣做沒有任何優勢。 – dutt 2010-10-15 06:47:23

1

你的問題的簡短答案是沒有義務聲明和定義模板類在同一個源文件中。

事實上,我認爲這是一件壞事,但它是完全可以理解的,因爲分開使用它們非常困難(但它可以完成!)。

編輯

假設你有

  • myTemplateClass。爲h,它聲明瞭一個模板類MyTemplateClass
  • myTemplateClass.hpp定義其類成員(包括myTemplateClass.h)
  • 使用MyTemplateClass的內部的main.cpp

只需包括在myTemplateClass.h main.cpp中和創建myTemplateClassInt.cpp如下:

#include "myTemplateClass.hpp" 

template MyTemplateClass<int>; 

這樣做,你告訴編譯器實例MyTemplateClass的模板參數「INT」的所有模板方法。由於它可以訪問myTemplateClass.hpp,所以這些方法將被完美地生成......並且鏈接器不會發生抱怨。

當然,這種方法要求您使用一些地方定義您的模板類的實例化版本。

+0

-----------如何? – lurscher 2011-07-12 18:31:51

+0

@lurscher:查看我的答案的編輯版本。 – 2011-07-13 07:51:00

相關問題