定义ostream运算符的Friend函数

jor*_*gen 0 c++ class operators friend ostream

我想定义一个ostream运算符,以方便我输出type的变量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() {}
};
Run Code Online (Sandbox Code Playgroud)

在源文件“ my_class.cpp”中,

#include "my_class.h"

void my_class::output(complex<double> cd) {
    cout << cd << endl;
}
Run Code Online (Sandbox Code Playgroud)

最后,我有一个主要的方法文件“ 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);

}
Run Code Online (Sandbox Code Playgroud)

我尝试使用编译

g++ -c my_class.cpp
Run Code Online (Sandbox Code Playgroud)

但这给了我错误

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) {
Run Code Online (Sandbox Code Playgroud)

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

g++ run_my_class.cpp my_class.o -o run_my_class
Run Code Online (Sandbox Code Playgroud)

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

mcs*_*rep 5

由于operator <<将在一个被称为std::ostream,你不能定义这个过程作为成员函数my_class,你必须把它定义为一个全球性的功能,因为它是一个操作std::ostream,没有my_class

通过将friend关键字放入声明中,意味着您要声明将其声明operator <<为朋友全局函数(而不是成员函数!)。C ++标准允许您在其中放置friend函数的定义,但它不会成为成员函数。它与以下内容相同,但更清楚:

#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;
}
Run Code Online (Sandbox Code Playgroud)

正如评论中已经指出的那样,friend此处没有必要使用。

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