当前位置:  开发笔记 > 编程语言 > 正文

如何正确地重载<<操作符为ostream?

如何解决《如何正确地重载<<操作符为ostream?》经验,为你挑选了5个好方法。

我正在用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&Math :: Matrix :: operator <<(std :: ostream&,const Math :: Matrix&)'必须只取一个参数

我对这个错误感到有些困惑,但是在6个月里做了大量的Java后,我的C++又变得有点生疏了.:-)



1> Johannes Sch..:

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

namespace Math
{
    class Matrix
    {
    public:

        [...]

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

该函数将自动定位到周围的命名空间Math(即使它的定义出现在该类的范围内),但除非您使用Matrix对象调用operator <<这将使参数相关的查找找到该操作符定义,否则将不可见.这有时可以帮助进行模糊调用,因为除了Matrix之外的参数类型它是不可见的.在编写其定义时,您还可以直接引用Matrix和Matrix本身定义的名称,而无需使用一些可能长的前缀限定名称并提供类似的模板参数Math::Matrix.



2> Mehrdad Afsh..:

你已宣布你的职能为friend.它不是班上的成员.您应该Matrix::从实现中删除.friend表示指定的函数(不是该类的成员)可以访问私有成员变量.实现该函数的方式就像一个Matrix类的实例方法,这是错误的.


您还应该在Math命名空间内声明它(不仅仅是使用使用命名空间Math).

3> kal..:

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


它不仅属于类,而且已正确定义_inside_ Math命名空间.此外,它还具有附加优势(可能不适用于Matrix,但可能不适用于其他类),'print'可以是虚拟的,因此打印将在最大的派生级别进行.
我不明白为什么这是一个向下投票,这澄清了你可以声明运算符在命名空间中,甚至不是作为朋友,以及如何声明运算符.
Mehrdad的答案没有任何代码片段,所以我只是通过将它移到命名空间本身的类之外来添加可能有用的东西.

4> 小智..:

假设我们谈论过载operator <<对源自所有类std::ostream来处理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;
    }                 
}



5> QuentinUK..:

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

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


@ Jean-MichaëlCelerierdecltype确保仅在存在t :: print时使用此运算符.否则它会尝试编译函数体并给出编译错误.
推荐阅读
谢谢巷议
这个屌丝很懒,什么也没留下!
DevBox开发工具箱 | 专业的在线开发工具网站    京公网安备 11010802040832号  |  京ICP备19059560号-6
Copyright © 1998 - 2020 DevBox.CN. All Rights Reserved devBox.cn 开发工具箱 版权所有