Reputation: 159
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
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
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