我有这个函数声明:
template<class T>
a::A& a::A::operator<<(T out) {
std::cout << out;
return (*this);
}
和这个函数定义:
namespace a {
...
class A {
...
template<class T> A& operator<<(T);
我称它为:
a::A b;
b << 1;
这是生成文件:
app: main.o A.o
g++ main.o A.o -o app
main.o: main.cpp
g++ -c main.cpp
A.o: A.cpp
g++ -c A.cpp
它给了我:
Undefined symbols: a::A& a::A::operator<< <int>(int)
这是为什么?
最佳答案
一旦 T
表示的类型(在您的情况下为 int
)实际已知,函数模板将在编译时转换为实际函数。但是,在编译main.cpp
之前,情况并非如此。 A.cpp
编译时,模板函数并没有实例化为实际函数,因此生成的目标文件不包含函数的二进制版本。
有两种方法可以解决这个问题。
在头文件中包含函数定义。即,使
template<class T> a::A& a::A::operator<<(T out) { std::cout << out; return (*this); }
头文件的一部分,并从
.cpp
文件中移除函数定义。这样做的效果是包含此 header 的任何
.cpp
文件将能够使用模板的任何实例化,即对于T
的任何值。或者,在
A.cpp
中包含显式模板实例化语句:template a::A& a::A::operator<<(int out);
这将导致编译器在编译
A.cpp
时实际实例化模板,并将编译后的函数包含在目标文件中。因此,链接器可以在将main.o
和A.o
链接在一起时找到它,一切都很好。缺点是它仅适用于您为其提供显式实例化的特定类型(在本例中,仅int
)。
关于c++ - 模板运算符重载函数上的 undefined symbol ,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/13150412/