From: Jerry Coffin on
In article <7bSdnQj0_PPCZYHWnZ2dnUVZ8gCdnZ2d(a)bt.com>,
francis.glassborow(a)btinternet.com says...

[ ... ]

> 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.

I would say rather the reverse: it allows the designer of a class to
give public access only to what should really be public. Just for
example, consider an overloaded operator<<, that's supposed to do
output to a stream. It can't be a member function, because the left
operand is going to be the stream, not the item being inserted in the
stream.

If we don't make the operator<< a friend of the class, then nearly
our only alternative is to give (at least indirect) access to the
object's externals to the whole world. Clearly giving that access
only to the operator<< is drastically superior.

While it's (theoretically) possible for this to have some effect on
run-time efficiency as well, it's 1) fairly unlikely to happen at
all, and 2) likely to be extremely trivial on the rare occasion that
it does happen.

> 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.

In most cases, there is no maintenance cost. Despite the fact that
syntactically it's a free function, the friend is logically part of
the class itself. The fact that the function you have to modify to
account for changes to the internals of the class doesn't have
"classname::" at the beginning of its name adds nothing to the
difficulty of the modification.

[ ... ]

> 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.

Quite the contrary: most of the time that you have to do such a
thing, you should use the friend function, and _eliminate_ the public
access functions. The world at large should not normally have access
to the object's internals, even via access functions.

--
Later,
Jerry.
From: Francis Glassborow on
Jerry Coffin wrote:
> In article <7bSdnQj0_PPCZYHWnZ2dnUVZ8gCdnZ2d(a)bt.com>,
> francis.glassborow(a)btinternet.com says...
>
> [ ... ]
>
>> 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.
>
> I would say rather the reverse: it allows the designer of a class to
> give public access only to what should really be public. Just for
> example, consider an overloaded operator<<, that's supposed to do
> output to a stream. It can't be a member function, because the left
> operand is going to be the stream, not the item being inserted in the
> stream.
>
> If we don't make the operator<< a friend of the class, then nearly
> our only alternative is to give (at least indirect) access to the
> object's externals to the whole world. Clearly giving that access
> only to the operator<< is drastically superior.
>

class xyz {
public:
void write(ostream &)const;
// rest of class definition
};

inline ostream & operator << (ostream & out; xyz const & inst){
inst.write(out);
return out;
}


Note that I can make write() a virtual function (and that, for me, is
the most significant reason for avoiding friends). I can also write:
template<class T>
inline ostream & operator << (ostream & out; T const & inst){
inst.write(out);
return out;
}

And that will work for every class that I provide a write function for.
No friend required.

In addition access functions do not necessarily give direct access to
the data, only to the external concept. I can rewrite the internals to
my hearts content and never have to touch the external functions. If I
take the friend route I have to re-implement every friend function when
I change the internals of my class.

friend is much over-rated and frequently over-used.
From: Kaz Kylheku on
On 2009-12-09, Francis Glassborow <francis.glassborow(a)btinternet.com> wrote:
> Jerry Coffin wrote:
>> In article <7bSdnQj0_PPCZYHWnZ2dnUVZ8gCdnZ2d(a)bt.com>,
>> francis.glassborow(a)btinternet.com says...
>>
>> [ ... ]
>>
>>> 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.
>>
>> I would say rather the reverse: it allows the designer of a class to
>> give public access only to what should really be public. Just for
>> example, consider an overloaded operator<<, that's supposed to do
>> output to a stream. It can't be a member function, because the left
>> operand is going to be the stream, not the item being inserted in the
>> stream.
>>
>> If we don't make the operator<< a friend of the class, then nearly
>> our only alternative is to give (at least indirect) access to the
>> object's externals to the whole world. Clearly giving that access
>> only to the operator<< is drastically superior.
>>
>
> class xyz {
> public:
> void write(ostream &)const;
> // rest of class definition
> };
>
> inline ostream & operator << (ostream & out; xyz const & inst){
> inst.write(out);
> return out;
> }

Goofball,

With this, you are not at all making the effective counterexample to Jerry's
informative posting that you /think/ you are.

You were not able to write the << operator as a non-friend, non-member
function, such that /it/ actually does all the work.

That part of your operator << which actually does the operation
had to be moved into the body of a new function, namely xyz::write, which /is/
a privileged member of the class.

So your point reduces to ``Every overloaded operator can be a trivial
non-member, non-friend inline function wrapper which calls some other
function (that /is/ itself a friend or member function). Therefore, an
overloaded operator never has to be a friend. Q. E. D. Worship my
stunning C++ brilliance!''
From: Jerry Coffin on
In article <mMadnZncP8l9cYPWnZ2dnUVZ8qmdnZ2d(a)bt.com>,
francis.glassborow(a)btinternet.com says...

[ ... ]

> class xyz {
> public:
> void write(ostream &)const;
> // rest of class definition
> };
>
> inline ostream & operator << (ostream & out; xyz const & inst){
> inst.write(out);
> return out;
> }

Ideally, a class interface should be minimal, yet complete -- this is
clearly redundant. It's perfectly fine to have a write member
function -- but the user should only see operator<<, so the correct
formulation is:

class xyz {
// protected:?
void write(ostream &) const;
public:
friend ostream &operator<<(ostream &, xyz const &);
};

> Note that I can make write() a virtual function (and that, for me, is
> the most significant reason for avoiding friends).

It's not a reason to avoid using a friend at all. Quite the contrary,
as Herb Sutter argued years ago[1], there are actually pretty good
reasons for virtual functions to be private or protected. Most people
consider this more or less a solution in search of a real problem --
and I _tend_ to agree. The usual argument against it is simply the
multiplication of functions, with what's usually seen as minimal or
nonexistent benefit.

Nonetheless, in this case we can do the right thing with no extra
effort. We're going to have a virtual function and a non-member, non-
virtual "front end" anyway -- so making the virtual function private
or improves the interface in two completely separate ways. There is
no benefit to 'write()' being public.

[1] http://www.gotw.ca/publications/mill18.htm

I can also write:
> template<class T>
> inline ostream & operator << (ostream & out; T const & inst){
> inst.write(out);
> return out;
> }
>
> And that will work for every class that I provide a write function for.
> No friend required.

It requires no friend, but it still exposes a redundant 'write()'
function as part of the interface.

> In addition access functions do not necessarily give direct access to
> the data, only to the external concept. I can rewrite the internals to
> my hearts content and never have to touch the external functions. If I
> take the friend route I have to re-implement every friend function when
> I change the internals of my class.

This is, of course, utterly false. Making 'write()' a private member
function causes _no_ change in 'operator<<' at all, neither when it
is written nor when the implementation of 'write()' is changed.

> friend is much over-rated and frequently over-used.

Public member functions, _especially_ virtual public member
functions, are much more so.

--
Later,
Jerry.
From: Alf P. Steinbach on
* Jerry Coffin:
> as Herb Sutter argued years ago[1], there are actually pretty good
> reasons for virtual functions to be private or protected.

It's just stupid to have virtual functions private except in some very special
cases. You loose the ability to assert that you're overriding something
existing. And you introduce a bug-vector or at least a dang-again-vector, since
whatever's introduced up in some base class, even though not accessible to you,
can be inadvertently overridden by you.

I remember that Herb argued something silly (handwaving a lot) about it.

It was on a par with and was essentially the same story as his use of
std::auto_ptr for PIMPL idiom; he corrected neither.


Cheers & hth.,

- Alf