定义ostream运算符的Friend函数

时间:2015-10-11 11:52:15

标签: c++ class operators friend ostream

我想定义一个ostream运算符,让我轻松输出alglib::complex类型的变量。为了提供一个不包含alglib库的工作示例,我将重载下面complex<double>的输出(由于该问题的早期版本,这个澄清)。在头文件“my_class.h”中我有

using namespace std;
#include <complex>
#include <iostream>

class my_class {

    public:

    ostream& operator << (std::ostream& os, complex<double> a) {
        os << "(" << real(a) << "," << imag(a) << ")";
        return os;
    }

    void output(complex<double>);

    my_class() {}
    ~my_class() {}
};

在源文件“my_class.cpp”中我有

#include "my_class.h"

void my_class::output(complex<double> cd) {
    cout << cd << endl;
}

最后我有一个主方法文件“run_my_class.cpp”:

#include "my_class.h"

int main(int argc, const char* argv[]) {

    my_class obj;
    complex<double> cd=complex<double>(1.0,-1.0);
    obj.output(cd);

}

我尝试使用

进行编译
g++ -c my_class.cpp

但这给了我错误

my_class.h:9:62: error: ‘std::ostream& my_class::operator<<(std::ostream&, std::complex<double>)’ must take exactly one argument
 ostream& operator << (std::ostream& os, complex<double> a) {

但是,如果我将运算符定义为朋友,即friend ostream& operator << (std::ostream& os, complex<double> a),则编译并编译main方法:

g++ run_my_class.cpp my_class.o -o run_my_class

它可以正常工作。但是,这不是friend关键字的用途。有没有更好的方法来使这项工作?

2 个答案:

答案 0 :(得分:5)

由于operator <<会调用std::ostream,因此您无法将此过程定义为my_class成员函数,您必须将其定义为std::ostream 全局功能,因为它是my_class的操作,而不是friend

通过将operator <<关键字放入声明中,您说要将#include <complex> #include <iostream> class my_class { public: friend ostream& operator << (std::ostream& os, complex<double> a); void output(complex<double>); my_class() {} ~my_class() {} }; std::ostream& operator << (std::ostream& os, complex<double> a) { os << "(" << real(a) << "," << imag(a) << ")"; return os; } 声明为朋友全局函数(不是成员函数!)。 C ++标准允许您在其中放置友元函数的定义,但它不是成员函数。它与以下相同,更清楚:

friend

正如评论中已经指出的那样,这里没有必要使用<div class="container-body"> <div class="rule"><hr></div> <h3>Software version:</h3> 10.0.0 <div class="rule"><hr></div> <h3>Operating system(s):</h3> AIX, Linux, Windows <div class="rule"><hr></div> <h3>Reference #:</h3> 7042947 <div class="rule"><hr></div> <h3>Modified date:</h3> <p>2015-04-02</p> </div>

与问题无关,但请注意,在头文件中解析命名空间通常是一个非常糟糕的主意,因为包括它在内的所有其他文件也会隐式地解析该命名空间。从长远来看,它很容易导致令人烦恼的编译错误。

答案 1 :(得分:1)

我不会称之为更好的方式,而是更明确的方式。

这是您的流媒体操作员:

ostream& operator << (std::ostream& os, complex<double> a) {
        os << "(" << real(a) << "," << imag(a) << ")";
        return os;
}

它的第一个参数是输出流。由于您无权访问输出流,因此您不能将输出流运算符用作成员函数,除非您将其作为类的朋友。

如果您想避免使用朋友,您可以随时将其定义为班级外部的功能,这是最常见的方式。