我有这个函数的声明:
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;
这是Makefile文件:
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
它给我:
未定义的符号:A :: A&A :: A ::运算符<< (INT)
这是为什么?
函数模板在编译时将变成一个实际的功能,一旦所代表的类型T
(即, int
你的情况)实际上是已知的。 然而,这并非如此前main.cpp
编译。 在当时间A.cpp
编译时,模板功能不实例化为实际的功能,因此目标文件生成不包括函数的二进制版本。
有两种方法来解决这个问题。
包括在你的头文件中的函数定义。 也就是说,使
template<class T> a::A& a::A::operator<<(T out) { std::cout << out; return (*this); }
头文件的一部分,并从该函数定义.cpp
文件。
这样做的效果是, 任何 .cpp
包括该头文件将能够使用的模板的任何实例,即,对于任何值T
。
另外,包括明确模板实例声明A.cpp
:
template a::A& a::A::operator<<(int out);
这将导致编译器实际上的实例化模板时A.cpp
编译,并包含目标文件中的编译功能。 因此,当链接链接可以找到它main.o
和Ao
在一起,所有的罚款。 缺点是,它只会为特定类型(在这种情况下,只有努力int
你所提供明确的实例)。
试着改变你的定义:
template<class T>
a::A& a::A::operator<< <T> (T out) {
std::cout << out;
return (*this);
}
?
(请确保它是在头文件)