流插入操作符<<为架构x86_64错误重载了未定义的符号

问题描述

我目前正在学习如何为我的班级重载流插入操作符。以下是我拥有的代码

#include <iostream>
#include <string>

using std::string;
using std::endl;
using std::cout;

template<typename T>
class A {
    public:
        A(T);
    friend std::ostream& operator<<(std::ostream&,const A&);
    T* value;
};

template<typename T>
A<T>::A(T input) {*value = input;}

template<typename T>
std::ostream& operator<<(std::ostream& out,const A<T>& obj) {
    out << *(obj.value);
    return out;
}

int main() {
    A<string> foo("HELLO");
    cout << foo << endl; 
    return 0;
}

使用G ++编译代码后出现此错误

Undefined symbols for architecture x86_64:
  "operator<<(std::__1::basic_ostream<char,std::__1::char_traits<char> >&,A<std::__1::basic_string<char,std::__1::char_traits<char>,std::__1::allocator<char> > > const&)",referenced from:
      _main in streamops-ef073c.o
ld: symbol(s) not found for architecture x86_64
clang: error: linker command Failed with exit code 1 (use -v to see invocation)

有什么主意吗?我正在遵循指南,看不到操作员重载的区别。

解决方法

问题在于friend声明将函数声明为非模板函数。

您需要将其声明为模板:

template<typename U>
friend std::ostream& operator<<(std::ostream&,const A<U>&);

(可选)您可以在类中内联定义函数:

friend std::ostream& operator<<(std::ostream& out,const A& obj) {
    return out << *(obj.value);
} 
,

一种选择是结合使用类成员函数和非成员函数。

template <typename T>
class A
{
    public:

        A(T);

        std::ostream& write(std::ostream& out) const
        {
           return out << *value;
        }

        T* value;
};


template <typename T>
std::ostream& operator<<(std::ostream& out,const A<T>& obj)
{
   erturn obj.write(out);
}


关于您定义班级方式的警告。

当调用构造函数时,您的代码将遇到未定义的行为。您正在使用

*value = input;

没有value初始化为指向有效对象。那不好。