如何正确地重载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; }