我正在用C ++编写一个用于矩阵运算的小型矩阵库。然而,我的编译器抱怨,在它之前没有。这段代码在架子上放置了6个月,之间我把我的电脑从debian etch升级到了lenny(g ++(Debian 4.3.2-1.1)4.3.2 但是我在具有相同g ++的Ubuntu系统上遇到了同样的问题。
以下是我的矩阵类的相关部分:
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:错误:'std :: ostream&amp; 数学::矩阵::运营商LT;≤(标准:: ostream的&安培;, const Math :: Matrix&amp;)'必须采取 恰好一个参数
我对这个错误感到有些困惑,但是在那6个月的大量Java之后,我的C ++又变得有点生疏了。 : - )
答案 0 :(得分:131)
告诉你另一种可能性:我喜欢使用朋友定义:
namespace Math
{
class Matrix
{
public:
[...]
friend std::ostream& operator<< (std::ostream& stream, const Matrix& matrix) {
[...]
}
};
}
该函数将自动定位到周围的命名空间Math
(即使其定义出现在该类的范围内),但除非您调用operator&lt;&lt;使用Matrix对象,它将使参数依赖查找找到该运算符定义。这有时可以帮助进行模糊调用,因为除了Matrix之外的参数类型它是不可见的。在编写其定义时,您还可以直接引用Matrix和Matrix本身定义的名称,而无需使用一些可能长的前缀限定名称并提供Math::Matrix<TypeA, N>
等模板参数。
答案 1 :(得分:118)
您已将自己的职能声明为friend
。它不是班上的成员。您应该从实现中删除Matrix::
。 friend
表示指定的函数(不是该类的成员)可以访问私有成员变量。实现该函数的方式类似于Matrix
类的实例方法,这是错误的。
答案 2 :(得分:72)
要添加到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;
}
答案 3 :(得分:60)
假设我们正在讨论为operator <<
派生的所有类重载std::ostream
来处理Matrix
类(而不是为<<
重载Matrix
(),在标题中的Math命名空间之外声明重载函数更有意义。
仅当无法通过公共接口实现功能时才使用友元功能。
<强> 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;
}
}
答案 4 :(得分:31)
在C ++ 14中,您可以使用以下模板打印任何具有T :: print(std :: ostream&amp;)const的对象;构件。
template<class T>
auto operator<<(std::ostream& os, const T& t) -> decltype(t.print(os), os)
{
t.print(os);
return os;
}
答案 5 :(得分:1)
我想用一个重载 <<
来打印数组的例子来简化一下。
<<
运算符周围传递两种对象类型#include<iostream>
using namespace std;
void operator<<(ostream& os, int arr[]) {
for (int i = 0;i < 10;i++) {
cout << arr[i] << " ";
}
cout << endl;
}
int main() {
int arr[10] = { 1,2,3,4,5,6,7,8,9,10 };
cout << arr;
}
如果还需要级联运算符,请确保返回 cout
对象
在重载函数如下,
#include<iostream>
using namespace std;
ostream& operator<<(ostream& os, int arr[]) {
for (int i = 0;i < 10;i++) {
cout << arr[i] << " ";
}
cout << endl;
return os;
}
int main() {
int arr[10] = { 1,2,3,4,5,6,7,8,9,10 };
int arr2[10] = { 11,22,33,44,55,66,77,88,99,100 };
// cascading of operators
cout << arr << arr2;
}