2009-08-30 117 views
24

我在調用模板類時遇到了問題。 我聲明瞭一個新的類型名稱Array,它是一個模板;C++模板,鏈接錯誤

在.HPP文件:

template <typename T> 
class Array 
{ 
public: 
    Array(); 
}; 

在.cpp文件:

template <typename T> 
Array<T>::Array() 
{ 
//Do something 
} 

在主:

Array<int> arr; 

我得到鏈接錯誤:無法解析的外部符號的構造函數。

任何想法?

+0

將這個問題鏈接到https://stackoverflow.com/questions/495021/why-can-templates-only-be-implemented-in-the-header-file是有用的,但它不是真的重複。 OP不知道在這個問題上完全假設的東西。 – Winter 2017-06-22 15:58:33

回答

47

模板功能,包括成員函數,必須在頭文件中編寫的。這意味着如果你有一個模板類,它的實現必須完全在頭部。這是因爲編譯器需要訪問整個模板定義(而不僅僅是簽名)才能爲模板的每個實例化生成代碼。

+0

是的,它的工作。 你可以添加更多解釋爲什麼你需要在頭文件中定義所有的解釋嗎?另外我添加的實現我在「endif」之前添加了所有,對吧? – 2009-08-30 14:24:29

+1

正確。有關爲什麼的一個很好的解釋,請參閱http://www.parashift.com/c++-faq-lite/templates.html#faq-35.12和以下與月亮陰影相關的問題35.13。 – 2009-08-30 14:29:00

+7

從技術上講,這不是一個要求。您可以在某個編譯單元中明確實例化該模板,並在其他地方使用該模板,但這需要相當多的手動內務管理(爲項目中使用的每種新類型添加顯式實例),甚至可能導致不可能(如果必須的話與尚未知的類型一起工作)。 – 2009-08-30 19:48:54

8

把這兩樣模板聲明和模板函數在頭文件 定義。大多數C++編譯器不輕鬆支持單獨的編譯模型模板,

3

你有這裏的問題是,你藏在.cpp文件中構造函數的定義。這個定義適用於所有類型T,包括T如您使用int,但實際上,因爲它仍然只是一個聲明,任何不提供的定義。
鏈接器找不到符號Array<int>::Array()。現在

,您可以添加這樣一行:

Array<int> arr1; 

您Array.cpp文件的末尾,這使得編譯器實例化的正確定義了鏈接所期待的。然而,這僅僅提供一個定義,的Array<int>並沒有其他。

該解決方案將工作,直到你需要不同的模板參數的Array,說:double,在這一點上,你將需要添加:

Array<double> arr2; 

您Array.cpp文件的末尾 - 現在你可以看到這是不可持續的!

如果您需要C++與任何類型一起使用,您可能需要將來,現在是將ctor的定義(以及大概所有其他成員函數)向上移動到標題(和刪除.cpp文件,因爲它不會留下任何東西)。

0

如上所述,在C++模板中,新方法的過程由編譯器在編譯時執行,問題是它需要在此期間知道thm的所有定義,因此所有的類/函數聲明都必須是ar h或hpp文件。

1

另一個答案,編譯只是你的.cpp文件(不是主),並檢查目標文件的大小,然後創建一個empty.cpp文件,然後編譯empty.cpp。最後比較兩個對象文件的大小。你會看到它們具有相同的大小,這意味着你的.cpp文件不需要編譯,所以鏈接器找不到任何東西。