简体   繁体   中英

Friend function defining an ostream operator

I would like to define an ostream operator to let me easily output variables of type alglib::complex . To provide a working example without including the alglib library I'll instead overload the output of complex<double> below (this clarification because of an earlier version of the question). In the header file "my_class.h" I have

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() {}
};

And in the source file "my_class.cpp" I have

#include "my_class.h"

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

Finally I have a main method file "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);

}

I try to compile using

g++ -c my_class.cpp

but this gives me the error

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) {

However, if I define the operator as a friend, namely friend ostream& operator << (std::ostream& os, complex<double> a) , it compiles and I compile the main method:

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

And it works as it should. However this is not what it seems the friend keyword is for. Is there a better way to make this work?

Since operator << will be called on an std::ostream , you cannot define this procedure as a member function for my_class , you have to define it as a global function , since it's an operation for std::ostream , not my_class .

By putting the friend keyword into the declaration, you are saying that you want to declare the operator << as a friend global function (not a member function!). The C++ standard lets you put the definition of the friend function there, but it won't be a member function. It is the same as the following, which is more clear:

#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;
}

As it was already pointed out in the comments, the usage of friend is not necessary here.

Irrelevant to the question, but please be aware that resolving namespaces in a header file is generally a really-really bad idea, since all other files including it will implicitly resolve that namespace too. It can easily lead to vexing compilation errors in the long run.

I wouldn't call it a better way but a more clear way.

Here's your stream operator again:

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

Its first parameter is the output stream. Since you do not have access to the output stream, you can't use the output stream operator as a member function unless you make it a friend of the class.

If you want to want to avoid using friend you can always define it as a function external to the class, and that is the most common way.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM