piquesel
piquesel

Reputation: 159

Overloading << operator in C++ requires friend

I'm learning C++ and specifically the operator overloading.

I have the following piece of code:

#include <iostream>
#include <string>

using namespace std;

class Vector2
{
private:
    float x, y;

public:
    Vector2(float x, float y)
        : x(x), y(y) {}
    Vector2 Add(const Vector2& other) const;
    Vector2 operator+(const Vector2& other) const;
    Vector2 operator*(const Vector2& other) const;
    friend ostream& operator << (ostream& stream, const Vector2& other);
    Vector2 Multiply(const Vector2& other) const;
};

ostream& operator << (ostream& stream, const Vector2& other)
{
    stream << other.x << ", " << other.y;
    return stream;
}

Vector2 Vector2::Add(const Vector2& other) const
{
    return Vector2(x + other.x, y + other.y);
}

Vector2 Vector2::operator+(const Vector2& other) const
{
    return Add(other);
}

Vector2 Vector2::Multiply(const Vector2& other) const
{
    return Vector2(x * other.x, y * other.y);
}

Vector2 Vector2::operator*(const Vector2& other) const
{
    return Multiply(other);
}

int main()
{
    Vector2 position(4.0f, 4.0f);
    Vector2 speed(0.5f, 1.5f);
    Vector2 powerup(1.1f, 1.1f);

    Vector2 result = position.Add(speed.Multiply(powerup));
    Vector2 result2 = position + speed * powerup;

    std::cout << result2 << std::endl;

    std::cin.get();
}

Question: if I want this to work, I need to declare my ostream& operator << as friend. Otherwise MS Studio tells me: "Function definition for operator << not found"!

I don't understand why. I don't need to declare the other operators as friend, so why is this necessary in this case?

Thanks.

Upvotes: 0

Views: 303

Answers (2)

rawrex
rawrex

Reputation: 4064

The operator<< must be defined as non-member function (as well as operator>>).

Let's take a look at the case when our class has defined the operator<< as a member function, we would have to do output like so:

// Member function, lhs is bound to implicit this
ostream& operator<<(ostream&) const; 
Myclass obj;
obj << std::cout;

Why so? Because you know that an overloaded operator is just a function. So, underlying call to this function looks like this:

obj.operator<<(std::cout);

If the operator is a member function, there's no other way. Since we can't modify the library.

So, in order for the operator to access private data members, i.e. the x and y, we have to declare it as a friend.

The arithmetic operators ordinarily should also be non-member functions, to allow conversions for either of the operands. Thought it is not required. These also should not change state of their operands and should produce a new value, which also stimulates to approach them from non-member function.

Also, I would advise you to get rid of the using namespace std and specify namespaces explicitly (or at least avoid mixing up).

Upvotes: 4

Lukas-T
Lukas-T

Reputation: 11340

Operators + and * are declared as member functions of Vector2, so they are naturally able to access private members of Vector2.

However, you can't declare canonical IO-operators (<< and >>) as member-functions. The line

friend ostream& operator << (ostream& stream, const Vector2& other);

is not a declaration of a member function. It simply allows the free/non-member function ostream& operator << (ostream& stream, const Vector2& other); to access private members of Vector2.

Without this line you should get the error

'Vector2::x': cannot access private member declared in class 'Vector2'

(or something similar)


However, the error

"Function definition for operator << not found"

could arise when you have split declaration and definition in your real code. If you have the line

friend ostream& operator << (ostream& stream, const Vector2& other);

in Vector2 you also declared a free function ostream& operator << (ostream& stream, const Vector2& other); and simultaneously make it a friend of Vector2.

If you remove this line, the function isn't declared anywhere. (Of course the last part is only speculation, but the best guess I've got)

Upvotes: 1

Related Questions