From: Pat on
Today I was reviewing some information about operator overloading
(http://www.learncpp.com/cpp-tutorial/92-overloading-the-arithmetic-operators/)
and the author make the comment that friend functions (as opposed to
member functions) were the best way to overload an operator when the
operands were not modified. It wasn't clear to me why that would be
though (why friend functions are preferred). Clarity?

Thanks for any comments on this. -Pat
From: Ulrich Eckhardt on
Pat wrote:
> Today I was reviewing some information about operator overloading [..]
> and the author make the comment that friend functions (as opposed to
> member functions) were the best way to overload an operator when the
> operands were not modified. It wasn't clear to me why that would be
> though (why friend functions are preferred). Clarity?

There are three aspects to this:
1. functions instead of memberfunctions
This gives you the symmetry so that you can create code where the class
you're overloading for is on the right side of the operand. A member
operator must have the 'this' object on the left otherwise. I guess the
author was referring to this.
2. symmetry
Using a non-member function allows you to overload operator+ for (T, int),
(int, T) or (T, T) in a similar way. This follows from point 1, but is more
an aesthetic part.
3. friend instead of non-friend
This gives you access to the internals of a type. Further, it allows you to
define the operators near to the code where the member operators are and to
also define them inline if you want.

Uli

From: Kaz Kylheku on
On 2009-12-05, Ulrich Eckhardt <doomster(a)knuut.de> wrote:
> Pat wrote:
>> Today I was reviewing some information about operator overloading [..]
>> and the author make the comment that friend functions (as opposed to
>> member functions) were the best way to overload an operator when the
>> operands were not modified. It wasn't clear to me why that would be
>> though (why friend functions are preferred). Clarity?
>
> There are three aspects to this:
> 1. functions instead of memberfunctions
> This gives you the symmetry so that you can create code where the class
> you're overloading for is on the right side of the operand. A member
> operator must have the 'this' object on the left otherwise. I guess the
> author was referring to this.
> 2. symmetry
> Using a non-member function allows you to overload operator+ for (T, int),
> (int, T) or (T, T) in a similar way. This follows from point 1, but is more
> an aesthetic part.
> 3. friend instead of non-friend
> This gives you access to the internals of a type.

So does a static member function.

> Further, it allows you to
> define the operators near to the code where the member operators are and to
> also define them inline if you want.

What? A static member function can also be be bear the code where the
member operators are. Typically, in the same source files where the
class is implemented, but not necessarily. Static functions can be
inline too.

The real reason for wanting to use friend functions is that a
function may be declared as a friend to more than one class,
whereas it can be a member of at most one class.

An overloaded binary operator may have to peek into the internals of two
different classes, and so it needs to be a member of one of them
and friend to the other, or friend to both.
From: Francis Glassborow on
Kaz Kylheku wrote:
> On 2009-12-05, Ulrich Eckhardt <doomster(a)knuut.de> wrote:
>> Pat wrote:
>>> Today I was reviewing some information about operator overloading [..]
>>> and the author make the comment that friend functions (as opposed to
>>> member functions) were the best way to overload an operator when the
>>> operands were not modified. It wasn't clear to me why that would be
>>> though (why friend functions are preferred). Clarity?
>> There are three aspects to this:
>> 1. functions instead of memberfunctions
>> This gives you the symmetry so that you can create code where the class
>> you're overloading for is on the right side of the operand. A member
>> operator must have the 'this' object on the left otherwise. I guess the
>> author was referring to this.
>> 2. symmetry
>> Using a non-member function allows you to overload operator+ for (T, int),
>> (int, T) or (T, T) in a similar way. This follows from point 1, but is more
>> an aesthetic part.
>> 3. friend instead of non-friend
>> This gives you access to the internals of a type.
>
> So does a static member function.

Since when? A static member function has no access at all, in any way to
instance data, only to static (i.e. class rather than instance) data

>
>> Further, it allows you to
>> define the operators near to the code where the member operators are and to
>> also define them inline if you want.
>
> What? A static member function can also be be bear the code where the
> member operators are. Typically, in the same source files where the
> class is implemented, but not necessarily. Static functions can be
> inline too.
I do not understand what you are on about. static member functions have
nothing to do with this issue.

>
> The real reason for wanting to use friend functions is that a
> function may be declared as a friend to more than one class,
> whereas it can be a member of at most one class.

No, the real reason for friends is efficiency. It allows a function to
cut corners and directly access an instances data rather than go through
access functions. A friend function is essentially part of the classes
interface and will need modification any time that the class designer
elects to change the data representation.

In general, inexperienced programmers would be well advised to keep
clear of friend functions until they understand when they are desirable
and hence worth paying the maintenance cost.

>
> An overloaded binary operator may have to peek into the internals of two
> different classes, and so it needs to be a member of one of them
> and friend to the other, or friend to both.

It would be very rare that this was the case. Mostly the class public
access functions will be sufficient. Only when performance issues become
a major issue should you revisit the use of friend versus public access
functions.

From: Kaz Kylheku on
On 2009-12-07, Francis Glassborow <francis.glassborow(a)btinternet.com> wrote:
> Kaz Kylheku wrote:
>> On 2009-12-05, Ulrich Eckhardt <doomster(a)knuut.de> wrote:
>>> Pat wrote:
>>>> Today I was reviewing some information about operator overloading [..]
>>>> and the author make the comment that friend functions (as opposed to
>>>> member functions) were the best way to overload an operator when the
>>>> operands were not modified. It wasn't clear to me why that would be
>>>> though (why friend functions are preferred). Clarity?
>>> There are three aspects to this:
>>> 1. functions instead of memberfunctions
>>> This gives you the symmetry so that you can create code where the class
>>> you're overloading for is on the right side of the operand. A member
>>> operator must have the 'this' object on the left otherwise. I guess the
>>> author was referring to this.
>>> 2. symmetry
>>> Using a non-member function allows you to overload operator+ for (T, int),
>>> (int, T) or (T, T) in a similar way. This follows from point 1, but is more
>>> an aesthetic part.
>>> 3. friend instead of non-friend
>>> This gives you access to the internals of a type.
>>
>> So does a static member function.
>
> Since when?

Since early 1980-something C++, probably.

> A static member function has no access at all, in any way to
> instance data, only to static (i.e. class rather than instance) data

A static member function of a class has access to the private members of that
class, static or not.

Access means permission not means. To have means of accessing a non-static
member, a static member function requires an instance. But that can be
obtained.

The real reason to use friend functions for overloaded operators (over static
functions) is that static functions simply cannot be overloaded operators.
It's not in the language.

Overloaded operators must be non-static member functions, or non-member
functions.

They cannot be static members, as I wrongly implied. Oops, sorry about that,
everyone!

So if for whatever reason you don't want overloaded operators to be member
functions, you must make them nonmember functions. If these functions need
access to the internals of the class(es) they work with, they have to be
friends.

That's all there is to it.