在模板操作符重载函数未定义的符号在模板操作符重载函数未定义的符号(Undefined symbol

2019-05-12 12:03发布

我有这个函数的声明:

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)

这是为什么?

Answer 1:

函数模板在编译时将变成一个实际的功能,一旦所代表的类型T (即, int你的情况)实际上是已知的。 然而,这并非如此前main.cpp编译。 在当时间A.cpp编译时,模板功能不实例化为实际的功能,因此目标文件生成不包括函数的二进制版本。

有两种方法来解决这个问题。

  1. 包括在你的头文件中的函数定义。 也就是说,使

     template<class T> a::A& a::A::operator<<(T out) { std::cout << out; return (*this); } 

    头文件的一部分,并从该函数定义.cpp文件。

    这样做的效果是, 任何 .cpp包括该头文件将能够使用的模板的任何实例,即,对于任何值T

  2. 另外,包括明确模板实例声明A.cpp

     template a::A& a::A::operator<<(int out); 

    这将导致编译器实际上的实例化模板时A.cpp编译,并包含目标文件中的编译功能。 因此,当链接链接可以找到它main.oAo在一起,所有的罚款。 缺点是,它只会为特定类型(在这种情况下,只有努力int你所提供明确的实例)。



Answer 2:

试着改变你的定义:

template<class T>
a::A& a::A::operator<< <T> (T out) {
    std::cout << out;
    return (*this);
}

(请确保它是在头文件)



文章来源: Undefined symbol on a template operator overloading function