如何正确地重载ostream的<<运算符?
我正在用C ++写一个矩阵运算的小型矩阵库。 然而,我的编译器抱怨,之前没有。 这个代码被放置在一个架子上6个月,之间我升级我的电脑从debian蚀刻到lenny(g ++(Debian 4.3.2-1.1)4.3.2),但是我有相同的问题,在Ubuntu系统相同的g ++ 。
这是我的矩阵类的相关部分:
namespace Math { class Matrix { public: [...] friend std::ostream& operator<< (std::ostream& stream, const Matrix& matrix); } }
而“实施”:
using namespace Math; std::ostream& Matrix::operator <<(std::ostream& stream, const Matrix& matrix) { [...] }
这是编译器给出的错误:
matrix.cpp:459:error:'std :: ostream&Math :: Matrix :: operator <<(std :: ostream&,const Math :: Matrix&)'必须只有一个参数
我对这个错误感到有点困惑,但是之后我的C ++在6个月的时间里做了大量的Java之后,已经变得有点生疏了。 🙂
你已经宣布你的功能为friend
。 这不是班上的成员。 你应该从实现中删除Matrix::
。 friend
意味着指定的函数(不是类的成员)可以访问私有成员变量。 你实现函数的方式就像是一个Matrix
类的实例方法是错误的。
只是告诉你另外一个可能性:我喜欢使用朋友定义:
namespace Math { class Matrix { public: [...] friend std::ostream& operator<< (std::ostream& stream, const Matrix& matrix) { [...] } }; }
该函数将被自动定位到周围的命名空间Math
(即使它的定义出现在该类的范围内),但是除非使用Matrix对象调用operator <<,否则将不可见,这会使得依赖于参数的查找找到该运算符定义。 这有时可以帮助模糊的调用,因为对于Matrix以外的参数类型是不可见的。 在编写它的定义的时候,你也可以直接引用Matrix定义的名字和Matrix本身,而不需要用一些可能的长前缀限定名字,并提供像Math::Matrix<TypeA, N>
这样的模板参数。
要添加到Mehrdad答案,
namespace Math { class Matrix { public: [...] } std::ostream& operator<< (std::ostream& stream, const Math::Matrix& matrix); }
在你的实现
std::ostream& operator<<(std::ostream& stream, const Math::Matrix& matrix) { matrix.print(stream); //assuming you define print for matrix return stream; }
假设我们正在讨论为所有从std :: ostream派生出来的类重载operator <<以处理Matrix类(而不是为Matrix类重载),那么在数组名称空间之外声明重载函数更有意义标题。
仅在通过公共接口无法实现功能时才使用朋友功能。
Matrix.h
namespace Math { class Matrix { //... }; } std::ostream& operator<<(std::ostream&, const Math::Matrix&);
请注意,运算符重载是在名称空间之外声明的。
Matrix.cpp
using namespace Math; using namespace std; ostream& operator<< (ostream& os, const Matrix& obj) { os << obj.getXYZ() << obj.getABC() << '\n'; return os; }
另一方面,如果你的超载函数确实需要成为一个朋友,即需要访问私有和受保护的成员。
MATH.H
namespace Math { class Matrix { public: friend std::ostream& operator<<(std::ostream&, const Matrix&); }; }
你需要用命名空间块来封装函数定义,而不是仅仅using namespace Math;
。
Matrix.cpp
using namespace Math; using namespace std; namespace Math { ostream& operator<<(ostream& os, const Matrix& obj) { os << obj.XYZ << obj.ABC << '\n'; return os; } }
在C ++ 14中,您可以使用以下模板来打印任何具有T :: print(std :: ostream&)const的对象; 会员。
template<class T> auto operator<<(std::ostream& os, const T& t) -> decltype(t.print(os), os) { t.print(os); return os; }