2011-11-02 111 views
2

我想編譯一個最小的例子,它實例化了一個模板類 。該示例在保留聲明的某個訂單 時編譯正常,否則失敗。C++模板聲明順序

temp.h:

#include <iostream> 
template <bool display> 
class test { 
    public: 
    void sayHi(); 
}; 

temp.cpp:

#include "temp.h" 
template <bool display> 
void test<display>::sayHi() { 
    if (display) std::cout << "Hi"; 
} 

main.cpp中:

#include <iostream> 
#include "temp.h" 
int main() { 
    test<true> myobject; 
    myobject.sayHi(); 
    return 0; 
} 

這是如何包括類標準。 在GCC 4.4.6,這個失敗,錯誤 的main.cpp :(文本+ 0x3a):未定義參考`測試:: sayHi的()」

然而,示例編譯當我做了的#include 「temp.cpp」代替main.cpp 文件中的#include「temp.h」,以便編譯器首先讀取temp.h中的類聲明,然後 將看到temp.cpp的內容,並且僅在此之後main.cpp中。

當我使用非模板類時,它可以很好地在main.cpp中包含.h文件 - 這裏出了什麼問題?請注意,temp.cpp包含在我的Makefile中的 ,所以它肯定不應該被編譯器遺忘。 感謝您的幫助。

+0

http://stackoverflow.com/questions/3705740/c-lnk2019-error-unresolved-external-symbol-template-classs-constructor-and/3705774#3705774 –

+1

單行摘要:模板不是類型,並且*類型*定義必須包含在(至少)一個翻譯單元中。 (在你的代碼中,'test '的類型定義不包含在* any * TU中。) –

回答

1

使用模板時,聲明和定義都必須位於同一個文件中。您可以通過將所有代碼放在一個文件中(並將函數定義嵌入或不嵌入,由您決定)還是將聲明和定義分開來完成此操作,但包括位於.h底部的定義文件文件

因此,這將是

tmp.h:

#include <iostream> 
template <bool display> 
class test { 
    public: 
    void sayHi(); 
}; 

#include "tmp.cpp" 

和tmp.cpp和main.cpp中保持不變(但你沒有編譯器,因爲編譯給tmp.cpp它包含在tmp.h中)。

許多人使用.template擴展名替換.cpp擴展名(它可以讓你知道它不會被編譯,加上它看起來比包含一個.cpp文件更加奇怪),所以它們中的模板函數定義的文件名是這樣的。但你不必這樣做。

+0

謝謝,這會清除它。 – AndOrXor