简体   繁体   中英

Error with << operator overload returning a std::string

I'm having troubles understanding the reason why the compiler accuses error, when the return type of a << operator overload is std::string . Could you please help me understand?

Bellow is an reproducible example, which gives a gigantic error.

class XY
{
    int X__;
    int Y__;
 public:
    XY(int x, int y):X__(x), Y__(y){}
    ~XY(){}

    std::string operator<<(const XY_cartesiano& c)
    {
        std::stringstream ss;
        ss << "{ " << X__ << ", " << Y__ << " }";
        return ss.str();
    }

    int x() const{return X__;}
    int y() const{return Y__;}
};

void main()
{

XY a(1,2);
std::cout << a;
}

Let's take something like this as an example:

cout << "My number is " << 137 << " and I like it a lot." << endl;

This gets parsed as

((((cout << "My number is ") << 137) << " and I like it a lot.") << endl);

In particular, notice that the expression cout << "My number is " has to evaluate to something so that when we then try inserting 137 with << 137 the meaning is "take 137 and send it to cout ."

Imagine if cout << "My number is " were to return a string . In that case, the << 137 bit would try to use the << operator between a string on the left-hand side and an int on the right-hand side, which isn't well-defined in C++.

The convention is to have the stream insertion operator operator << return a reference to whatever the left-hand side stream is so that these operations chain well. That way, the thing on the left-hand side of << 137 ends up being cout itself, so the above code ends up essentially being a series of chained calls to insert things into cout . The signature of these functions therefore usually look like this:

ostream& operator<< (ostream& out, const ObjectType& myObject) {
     // ... do something to insert myObject into out ... //
     return out;
}

Now, everything chains properly. Notice that this function is a free function, not a member function, and that the left-hand side is of type ostream and the right-hand side has the type of your class in it. This is the conventional way to do this, since if you try overloading operator << as a member function, the left-hand side will be an operand of your class type, which is backwards from how stream insertion is supposed to work. If you need to specifically access private fields of your class in the course of implementing this function, make it a friend:

class XY {
public:
      ...
      friend ostream& operator<< (ostream& out, const XY& myXY);
};

ostream& operator<< (ostream& out, const XY &myXY) {
    ...
    return out;
}

Correct way to overload << operator in your case is

ostream& operator<<(ostream& os, const XY& c)  
{  
    os << c.X__ <<" "<< c.Y__ ;
    return os;  
}

You have overloaded operator<< in a way that's incompatible with the conventions you must follow when you intend to use the operator with a std::ostream object like std::cout .

In fact, your operator<< 's signature has nothing to do with streams at all! It is just a member function of XY which takes another XY (which it then does not use), returns a string and has an unsual name. Here's how you would theoretically call it:

XY a(1,2);
XY b(1,2);
std::string x = (a << b);

The correct way to overload operator<< for use with streams is to make the operator a non-member function, add a stream reference parameter and return a stream reference to the stream argument. You also do not need a string stream; you write directly to the stream you get:

#include <iostream>

class XY
{
    int x;
    int y;
public:
    XY(int x, int y) : x(x), y(y) {}

    int X() const { return x; }
    int Y() const { return y; }
};

std::ostream& operator<<(std::ostream& os, XY const& c)
{
    os << "{ " << c.X() << ", " << c.Y() << " }";
    return os;
}

int main()
{
    XY a(1,2);
    std::cout << a;
}

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