Topic: Should friends obey access?


Author: warsaw@nlm.nih.gov (Barry A. Warsaw)
Date: 5 Oct 92 23:11:26 GMT
Raw View
Here's something I've been thinking about for a little while.  Why not
have friend declarations obey access specification?  Thus, declaring
something as a friend would only extend friendship to the part of the
interface in which the declaration was included.  Here's a concrete
example:

class Me
{
public:
 Me();
 void worldCanCallMe() {};

protected:
 friend class Buddy;
 void derivedAndBuddiesCanCallMe() {};

private:
 friend class Spouse;
 void spouseAndICanCallMe() {};
};


class Buddy
{
 void doit()
 {
  Me theMe;
  theMe.worldCanCallMe();
  theMe.derivedAndBuddiesCanCallMe();
  theMe.spouseAndICanCallMe();   // would be error, but isn't
 };
};


class Spouse
{
 void doit()
 {
  Me theMe;
  theMe.worldCanCallMe();
  theMe.derivedAndBuddiesCanCallMe();
  theMe.spouseAndICanCallMe();
 };
};


class Derived : public Me
{
 void doit()
 {
  worldCanCallMe();
  derivedAndBuddiesCanCallMe();
  spouseAndICanCallMe();     // error now and still would be
 };
};


class Stranger
{
 void doit()
 {
  Me theMe;
  theMe.worldCanCallMe();
  theMe.derivedAndBuddiesCanCallMe();  // error now and would be
  theMe.spouseAndICanCallMe();   // error now and would be
 };
};



Some issues that I can see:

1. What would be the point of declaring a friend in the public: section?
 a. useless but harmless
 b. give it special meaning

2. Backward compatibility?
 a. adopt 1a above and give public friends access to private members
 b. compilers give grace period on anachronism

I often find myself wanting to extend friendship to only part of the
interface of a class.  In these particular situations, derivation just
for interface sharing would be a compromise of the design, and I
really don't want friends to have access to private data members.
Basically, I want a non-derived class to have the same access as
derived classes so that I can exactly specify the interface for
friends, instead of just giving them blanket access. My current
solution is to put the friend declaration in the protected area
(currently meaningless) and only use protected members by convention.

Seems like it would be pretty easy to adopt, both from a language
standard and from an implementation viewpoint.  Besides, friendship
declarations are one thing (the only?) where access specification is
ignored. Anyway, I'm just throwing this out for discussion.  Makes
sense to me, but maybe others don't run into this situation very
often?

-Barry




Author: nh@cbnewsg.cb.att.com (nicholas.hounsome)
Date: 6 Oct 92 08:45:55 GMT
Raw View


Author: dak@tabaqui.informatik.rwth-aachen.de (David Kastrup)
Date: 9 Oct 92 18:07:58 GMT
Raw View
Friends are usually designed along with a class. Whereas derived classes
are designed in a later development step, friends are designed alongo
with the class. Consequently there is not much harm in giving
friends the same access as class members.

If some function needs access to protected parts of your interface,
you can still define it as a friend of the appropriate derived class,
where it probably belongs. Declaring someone to be your friend who is
not in the same compilation unit as yourself may be considered foolish.

But remember, C++ tries to protect from accident, not from fraught.
To split the meaning of friends would really not gain much, except
a feeling of security when compiling friends which are not designed
by yourself.