2011-11-02 114 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