Sho*_*hoe 3 c++ templates namespaces operator-overloading
我有此函数声明:
template<class T>
a::A& a::A::operator<<(T out) {
std::cout << out;
return (*this);
}
Run Code Online (Sandbox Code Playgroud)
和此函数定义:
namespace a {
...
class A {
...
template<class T> A& operator<<(T);
Run Code Online (Sandbox Code Playgroud)
我称之为:
a::A b;
b << 1;
Run Code Online (Sandbox Code Playgroud)
这是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
Run Code Online (Sandbox Code Playgroud)
它给了我:
未定义的符号: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);
}
Run Code Online (Sandbox Code Playgroud)
头文件的一部分,然后从.cpp文件中删除函数定义。
这样的效果是,包含此标头的任何 .cpp文件都将能够使用模板的任何实例化,即对于的任何值T。
或者,在中包含一个显式模板实例化语句A.cpp:
template a::A& a::A::operator<<(int out);
Run Code Online (Sandbox Code Playgroud)
这将导致编译器在编译时实际实例化模板A.cpp,并将编译后的函数包含在目标文件中。因此,在连接时链接器能够找到它main.o和A.o在一起,所有的罚款。缺点是,它仅适用于int您为其提供了显式实例化的特定类型(在这种情况下,仅适用于)。