Brian
Brian

Reputation: 113

Can ostream overloading be a function member?

I have a class Counter and I want to overload operator << to output the data member of Counter. I tried to make the ostream overloading a member function:

Counter{
public:
    std::ostream& operator<<(std::ostream& outStream, const Counter& c);
private:
    int count_;
};

std::ostream& Counter::operator<<(std::ostream& outStream, const Counter& c){
    outStream << c.count_;
    return outStream;
}

But the g++ compiler always outputs the same error:

‘std::ostream& Counter::operator<<(std::ostream&, const Counter&)’ must take exactly one argument

However, if I changed the overloading function to be a friend of the class, it worked all well, like this:

Counter{
public:
    friend std::ostream& operator<<(std::ostream& outStream, const Counter& c);
private:
    int count_;
};

std::ostream& operator<<(std::ostream& outStream, const Counter& c){
    outStream << c.count_;
    return outStream;
}

Does this mean that the the stream operator overloading cannot be a member function of a class?

Upvotes: 3

Views: 3590

Answers (4)

Sqeaky
Sqeaky

Reputation: 1936

Unfortunately the useful overloads for the streaming output operators ( << ) cannot be class members, because the ostream& must be on the left in use and declaration. They do not need to be friends of the class you wish to stream unless they need access to protected or private members. This means that if you can implement a streaming operator using just public functions such as observers/accessors without declaring it a friend.

In your first Counter class you are declaring a member function of the class that does not seem valid. In the second example of the Counter class you are stating that your operator overload for << , which seems valid, has access to the private members. In the second example the function must still be declared outside the class.

Wikipedia Operators in C and C++ has a good list of possible operator overloads, including the in class << overloads even though they are not very useful. The in class overloads must be called backwards CounterInstance << cout; which is counterintuitive.

Upvotes: 2

Ben Voigt
Ben Voigt

Reputation: 283893

It doesn't have to be a friend, but it can't be a member. Member operators only work when they are inside the class which corresponds to the left-hand operand.

Upvotes: 2

hmjd
hmjd

Reputation: 122011

Add a public query method that returns the value of count_, then it does not have to be a friend:

Counter{
public:
    int count() const { return count_; }
private:
    int count_;
};

std::ostream& operator<<(std::ostream& outStream, const Counter& c){
    outStream << c.count();
    return outStream;
}

Upvotes: 3

ikottman
ikottman

Reputation: 2004

If you put the ostream operator in the class itself then it will not work the way you expect it to. It would be a member function meaning to invoke it one would have to do this: c.operator<<("output") which is obviously not what you mean to do. For it to work as you expect an ostream operator it must be outside the class. You can do this by making it a friend or just put it outside of the class and use getters (accessors) to output the data.

Upvotes: 2

Related Questions