问题描述
我目前正在学习如何为我的班级重载流插入操作符。以下是我拥有的代码:
#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;
}
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
初始化为指向有效对象。那不好。