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