[comp.lang.c++] Suggestion for enhancing member access mechanism

jps@cs.brown.edu (John Shewchuk) (08/31/89)

The following describes an annoying situation that occurs with the
protection mechanism present in C++.  Following this is a possible
solution and a syntax that is reasonably backward compatible with the
current versions of C++.

The Situation
--- ---------

Given a class, X, and another class, Y, that is a friend class of the
first class, X; we might want classes derived from Y to have access to
the non-public members of X.

For example, if we have a class Vector, and a friend of Vector, FFT,
we could define a special version of FFT, Probabilistic_FFT, that
performs the same functions as FFT but implements them in a slightly
different way.

Given the current definition of the protection mechanisms and the
situation above; in order for classes derived from Y to have
access to the non-public parts of X we must explicitly list them as
friends in X.  

This is somewhat analogous to the situation that occurs with protected
members.  In that case, the derived class has access to the non-private
members of the base class.  The protected keyword eliminates the need to
make many friend declarations and recompile the base class each time
you derive something from it.

Likewise it would be useful to avoid the same thing when deriving from
Y.  In the Vector example, you could eliminate the need to edit and
recompile Vector each time we derive something from FFT that needs
fast access to Vector.

This situation seems to show up fairly often.  We have noticed it in
simulators and window systems as well as general purpose code like the
example described above.

Proposal
--------

The situation described above is mitigated if classes derived
from Y have non-private access to members of X.  This does not appear
to put major holes in the access mechanism since the access to the
members of X is like the access to the members of Y - there's nothing
that you could not do by adding member functions to Y to provide this
access. 


Syntax Suggestion
------ ----------

This is merely a suggested syntax.  If you have a better one, that
would be fine.

How about this: if the friend declaration appears in the private area
of a class definition then the friend has complete access to the
class.  This is just like the current situation.  However, unlike the
current situation, classes derived from the friend only have access to
the non-private members of the original class.

If the friend declaration appears in the protected area of a class
definition then the friend has access only to the non-private members
of the class.  Class derived from the friend class have the same
access rights.

It would not make sense to place friend declaration in the public area
of a class definition.

It has been suggested that programmers place the friend declarations
at the top of the class; if this is done then these changes should not
break existing code.  It may however provide more access than people
expected. 

Additionally, by using the scope resolution operator, you would be
able to manipulate the access rights for not only classes you are
derived from but also the classes to which you have access rights.
See the example below.


Example
-------

class Y;
class Y1;
class Z;

class X
{
private:
friend class Y;
  int a;
protected:
friend class Y1;
  int b;
  int B();
  int C();
public:
  int A();
};

class Y 
{
  int A(X& arg1) { arg1.a++; }  	// Access to a okay since friend.
}

class Y1
{
  int A(X& arg1) { arg1.a++; }		// Error, only non-private access
}					//  since friend in protected area.


class Z : public Y
{
private:
  X::B;					// Change access of X members.
public:
  X::C;					// Error, can't promote.
  int A(X& arg1) { 
    arg1.a++;				// Error, only protected allowed.
    arg1.b++;				// Okay since Z isa Y so it gets
  }					//   non-private access.
}  

Sincerely,

John Shewchuk				Brown University
Moises Lejter




John Shewchuk, Box 1910                                      jps@cs.brown.edu
Computer Science Dept
Brown Station, 02912

kvt@drutx.ATT.COM (TranKV) (09/01/89)

In article <13921@brunix.UUCP> jps@cs.brown.edu (John Shewchuk) writes:
>
>The Situation
>--- ---------
>
>Given a class, X, and another class, Y, that is a friend class of the
>first class, X; we might want classes derived from Y to have access to
>the non-public members of X.
>

According to 
        UNIX System V 
        AT&T C++ Language System 
        Release 2.0
        Product Reference Manual

that's the way it's supposed to work. The manual states under subsection
11.4 "friends":
        "Friendship is inherited but not transitive."
		       ^^^^^^^^^
However, I did try the scenario with Cfront 2.0 and got a syntax error 
for having derived class of Y access private member of class X.

[ John proposes a mechanism for tying access specifier 'friend' with 
  other access specifiers such as 'protected', 'private'. ]

>How about this: if the friend declaration appears in the private area
>of a class definition then the friend has complete access to the
>class.  This is just like the current situation.  However, unlike the
>current situation, classes derived from the friend 
>only have access to the non-private members of the original class.
 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
You mean "have access to all members of the original class." ??

[ ... other cases ... ]


The proposal looks very interesting since it specializes the scoping of
declarator 'friend'. However, I suspect that, in the first place, we 
have a compiler bug in Cfront 2.0 instead of a lack of features in 
C++ language definition.

Kim Tran
Bell Labs, Denver, CO