2009-06-10 28 views
1

我有一个很难得到这个工作C++重载运算符声明和定义问题

file: myclass.hpp 

Class MyClass { 
public: 
    template <class T>  
    MyClass &operator<<(const T &val); 
}; 


file: myclass.cpp 

template <class T> 
MyClass &MyClass::operator<<(const T &val) { 
    ... 
} 

我可以在一个对象编译这个没有问题,但是当其他功能尝试调用它,这个错误(每次使用< <)。

myclass.cpp: undefined reference to `MyClass& MyClass::operator<< <int>(int const&)' 

我在做什么错了?

回答

8

如果你想在单独的编译单元中定义模板的实例(通常是这种情况),那么你不能在单独的cpp中定义模板方法。在编译使用该模板类的编译单元时,每个模板方法必须对编译器可见。因此,跨cpps使用模板时,必须在标题中定义模板。模板是真正的生成类的方法,而不是自己的类。因此,当编译器看到

YourClass<int> 

它需要看到整个YourClass模板在编译时生成一个名为

YourClass<int> 

和类型所有的方法,这些方法具有发言权

完全不同的方法
YourClass<float> 

这意味着它必须看到所有的C++源代码。如果模板的这两个用途在单独的cpp中实例化,那么编译器可以同时生成的唯一方法是在一个头中完全定义模板。

查看我的回答here了解更多信息。

感谢您的宝贵意见,极大地改善了这个答案

+1

+1,主要是正确的,但只要您手动实例化将在应用程序中使用的所有类型,就可以在.cpp文件中实现您的模板定义。也就是说,定义后添加:'template class YourClass ;模板类YourClass ; ...' – 2009-06-10 17:30:02

4

将运算符的定义放入.hpp而不是.cpp。编译器需要能够在实例化某个新类型时看到模板的完整定义,以便它可以生成此特化的代码。

C++ FAQ Lite中,还有一些关于此类模板相关链接程序错误和不同可能解决方案的问题和解答。

2

模板需要在头文件,而不是cpp文件中定义。实际的实现是在每个编译单元按需使用时创建的。在这方面它们有点像宏。