如何正确超载<< operator for an ostream? [duplicate]

问题描述 投票:0回答:6

我正在用 C++ 编写一个用于矩阵运算的小型矩阵库。然而,我的编译器抱怨了,而以前却没有。这段代码被搁置了六个月,期间我将计算机从 Debian 4.0 (Etch) 升级到 Debian 5.0 (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& 数学::矩阵::运算符<<(std::ostream&, const Math::Matrix&)' must take exactly one argument

我对这个错误有点困惑,但是在这六个月做了很多 Java 之后,我的 C++ 又变得有点生疏了。 :-)

c++ namespaces operator-overloading iostream ostream
6个回答
157
投票

只是告诉您另一种可能性:我喜欢使用朋友定义:

namespace Math
{
    class Matrix
    {
    public:

        [...]

        friend std::ostream& operator<< (std::ostream& stream, const Matrix& matrix) {
            [...]
        }
    };
}

该函数将自动定位到周围的命名空间

Math
(即使它的定义出现在该类的范围内),但除非您调用运算符<< with a Matrix object which will make argument dependent lookup find that operator definition. That can sometimes help with ambiguous calls, since it's invisible for argument types other than Matrix. When writing its definition, you can also refer directly to names defined in Matrix and to Matrix itself, without qualifying the name with some possibly long prefix and providing template parameters like
Math::Matrix<TypeA, N>
,否则该函数将不可见。


145
投票

您已将函数声明为

friend
。它不是班级成员。您应该从实现中删除
Matrix::
friend
表示指定函数(不是类的成员)可以访问私有成员变量。您实现该功能的方式就像
Matrix
类的实例方法,这是错误的。


92
投票

添加到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;
 }

80
投票

假设我们正在讨论从

operator <<
派生的所有类重载
std::ostream
来处理
Matrix
类(而不是为
<<
类重载
Matrix
),则声明重载函数更有意义在标头中的 Math 命名空间之外。

仅当功能无法通过公共接口实现时才使用友元功能。

矩阵.h

namespace Math { 
    class Matrix { 
        //...
    };  
}
std::ostream& operator<<(std::ostream&, const Math::Matrix&);

请注意,运算符重载是在命名空间之外声明的。

矩阵.cpp

using namespace Math;
using namespace std;

ostream& operator<< (ostream& os, const Matrix& obj) {
    os << obj.getXYZ() << obj.getABC() << '\n';
    return os;
}

另一方面,如果您的重载函数确实需要成为好友,即需要访问私有和受保护的成员。

数学.h

namespace Math {
    class Matrix {
        public:
            friend std::ostream& operator<<(std::ostream&, const Matrix&);
    };
}

您需要用命名空间块将函数定义括起来,而不仅仅是

using namespace Math;

矩阵.cpp

using namespace Math;
using namespace std;

namespace Math {
    ostream& operator<<(ostream& os, const Matrix& obj) {
        os << obj.XYZ << obj.ABC << '\n';
        return os;
    }                 
}

49
投票

在 C++14 中,您可以使用以下模板来打印任何具有 T::print(std::ostream&)const; 的对象;会员。

template<class T>
auto operator<<(std::ostream& os, T const & t) -> decltype(t.print(os), os) 
{ 
    t.print(os); 
    return os; 
} 

在C++20中可以使用概念。

template<typename T>
concept Printable = requires(std::ostream& os, T const & t) {
    { t.print(os) };
};

template<Printable T>
std::ostream& operator<<(std::ostream& os, const T& t) { 
    t.print(os); 
    return os; 
} 

4
投票

我想用一个重载

<<
来打印数组的示例来稍微简化一下。

  1. 首先将两种对象类型传递给
    <<
    运算符
  2. 创建一个函数来重载运算符,如下所示。
#include<iostream> 
using namespace std;

void operator<<(ostream& os, int arr[]) {
    for (int i = 0;i < 10;i++) {
        os << arr[i] << " ";
    }
    os << 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;
}
© www.soinside.com 2019 - 2024. All rights reserved.