Topic: Proposal: friends with restrictions


Author: steve@lia.com (Stephen Williams)
Date: Thu, 23 Feb 1995 19:31:36 GMT
Raw View
In article <russgold-1702950031480001@slip-19.netaxs.com> russgold@netaxs.com (Russell Gold) writes:

   Hmm, I hate to say "never mind," but I think that my proposed syntax isn't
   going to achieve what I want to anyway.  As I said, the goal is to present
   some well-defined multiple sets of interfaces to a single class so that
   the compiler can limit a client's access appropriately - much the way a
   standard connector in a hardware system prevents inadvertant access to
   internals, while allowing for my than one kind of client.

   I really believe that there is value in this, but I'm not sure what the
   appropriate solution should be... oh well, I'll come back to it if I think
   of something useful.

How 'bout this:

 class Bar;
 class Foo  {
  friend class Bar;

     private:
  int i_am_accessible_to_Bar;

  class Safe { friend class Foo;
   int i_am_REALLY_private;
   [...etc...]

  } safe_even_from_friends;

 };

Foo has very precise control of what's public, what's private and
accessible to friends, and what's *really* private. I believe this
deals with the original issue of this thread without the need for a
language extension.

--

Stephen 2. Williams
 Work: steve@lia.com
 Home: steve@icarus.com

    Fight License Managers! Buy from
    vendors who use honor system!




Author: pstemari@erinet.com (Paul J. Ste. Marie)
Date: 21 Feb 1995 01:17:07 GMT
Raw View
In article <9502151658.AA14730@phoney.he.boeing.com>,
bvej18@phoney.boeing.com says...
>
>... It is very common that only a
>subset of the members are germane to a particular client. I therefore
>propose a modification to the "friend" concept. ....

You can already do this.  Modifying your example a bit, try this:

class Server {
  public:
   class ClientAInterface {
    protected:
     void aRoutineNeededByClientsAandB(Server& server) const;
     void aRoutineNeededOnlyByClientA(Server& server) const;
     };
   friend ClientAInterface;

   class ClientBInterface  {
    protected:
     void aRoutineNeededByClientsAandB(Server& server) const;
     };
    friend ClientBInterface;

    :

  private:
    void aRoutineNeededByClientsAandB();
    void aRoutineNeededOnlyByClientA();
    void aRoutineUsedByServerOnly();
    };

inline void Server::ClientAInterface::aRoutineNeededOnlyByClientA(
        Server& server) const {server.aRountineNeededOblyByClientA();}

inline void Server::ClientAInterface::aRoutineNeededByClientsAandB();(
        Server& server) const {server.aRoutineNeededByClientsAandB();}

inline void Server::ClientBInterface::aRoutineNeededByClientsAandB();(
        Server& server) const {server.aRoutineNeededByClientsAandB();}

Client A inherits from Server::ClientAInterface, and likewise for Client B.






Author: fenster@ground.cs.columbia.edu (Sam Fenster)
Date: 15 Feb 1995 23:05:43 GMT
Raw View
bvej18@phoney.boeing.com (Russ Gold) writes:
> it still seems too broad, as the friend (and all of its subclasses, if it is
> a class), can then access *everything.* It is very common that only a subset
> of the members are germane to a particular client.

First of all, the subclasses of a friend *can't* access the private members of
the friendship grantor.  Secondly, this is the second time in recent weeks
that someone has proposed this here, and I think you don't understand the
purpose of friendship:

When you implement a class, you write the code that handles private data, and
you write it correctly.  Then, you don't have to worry that users of your
class will manipulate the private data incorrectly.  But member privacy is not
meant to prevent the *implementor* from handling it incorrectly!  And there is
no need to shield one method from another!

Like a member, a friend class or function is also an integral part of the
design of the class that declares friendship.  Some things shouldn't be
formulated as members, but they are still part of the implementation of a
class.  These are friends.  They're not "clients."  (If anything, they're
"servers" -- the grantor cannot fulfil its purpose without the friend; the
friend services the inner workings of the grantor.)  *Users* of the grantor or
the friend are not granted access to privates.

But you cannot protect the *implementor* from doing something wrong.  The
class' implementation is fixed in size (closed).  It cannot be extended by a
user.  It's pointless to protect one existing piece of a class from another.




Author: russgold@netaxs.com (Russell Gold)
Date: Thu, 16 Feb 1995 00:01:21 -0500
Raw View
In article <FENSTER.95Feb15180545@ground.cs.columbia.edu>,
fenster@ground.cs.columbia.edu (Sam Fenster) wrote:

> bvej18@phoney.boeing.com (Russ Gold) writes:
> > it still seems too broad, as the friend (and all of its subclasses, if it is
> > a class), can then access *everything.* It is very common that only a subset
> > of the members are germane to a particular client.
>
> First of all, the subclasses of a friend *can't* access the private members of
> the friendship grantor.  Secondly, this is the second time in recent weeks
> that someone has proposed this here, and I think you don't understand the
> purpose of friendship:
>
> When you implement a class, you write the code that handles private data, and
> you write it correctly.  Then, you don't have to worry that users of your
> class will manipulate the private data incorrectly.  But member privacy is not
> meant to prevent the *implementor* from handling it incorrectly!  And there is
> no need to shield one method from another!

I don't recall saying anything about using this mechanism to prevent the
implementor from making mistakes.  I was specifically speaking of a class
having different interfaces for different clients. I proposed using the
"friend" notation because it is similar in terms of effect, in that
specific classes are granted access to certain members of a class not
available to the public.  It is certainly possible to write the program
correctly, so that no other class actually accesses those members, but
then again, if that is our solution, we can simply make everything
"public" and forget about protected and private members.

> Like a member, a friend class or function is also an integral part of the
> design of the class that declares friendship.  Some things shouldn't be
> formulated as members, but they are still part of the implementation of a
> class.  These are friends.  They're not "clients."  (If anything, they're
> "servers" -- the grantor cannot fulfil its purpose without the friend; the
> friend services the inner workings of the grantor.)  *Users* of the grantor or
> the friend are not granted access to privates.

Also an integral part of the design of a class is the collection of
services which it provides. Many classes provide more than one set of
services to different clients. I am simply looking for a way to use the
compiler to help enforce this and at the same time make the design and
implementation more similar to each other.

>
> But you cannot protect the *implementor* from doing something wrong.  The
> class' implementation is fixed in size (closed).  It cannot be extended by a
> user.  It's pointless to protect one existing piece of a class from another.

Can you tell me what in my proposal makes you think that I am trying to
protect one part of a class from another part of the same class?
------------------------------------------------------------------------
Russell Gold                     | "... society is tradition and order
russgold@netaxs.com (preferred)  | and reverence, not a series of cheap
russgold@aol.com                 | bargains between selfish interests."
russgold@boeing.com              |




Author: girod@dshp01.trs.ntc.nokia.com (Marc Girod)
Date: 17 Feb 1995 07:55:24 GMT
Raw View
Please see my follow-up to an other related posting:

From: girod@dshp01.trs.ntc.nokia.com (Marc Girod)
Newsgroups: comp.std.c++
Subject: Re: Proposal:    'protected friend:'
Date: 17 Feb 1995 07:24:13 GMT
In-reply-to: jcox@splinter.coe.neu.edu's message of 15 Feb 1995 20:06:16 GMT
Message-ID: <GIROD.95Feb17092413@dshp01.trs.ntc.nokia.com>
--
+-----------------------------------------------------------------------------+
| Marc Girod - Nokia Telecommunications       Phone: +358-0-511 27703         |
| TL4E - P.O. Box 12                            Fax: +358-0-511 27432         |
| SF-02611 Espoo 61 - Finland              Internet: marc.girod@ntc.nokia.com |
|    X.400: C=FI, A=Elisa, P=Nokia Telecom, UNIT=TRS, SUR=Girod, GIV=Marc     |
+-----------------------------------------------------------------------------+




Author: russgold@netaxs.com (Russell Gold)
Date: Fri, 17 Feb 1995 00:31:48 -0500
Raw View
Hmm, I hate to say "never mind," but I think that my proposed syntax isn't
going to achieve what I want to anyway.  As I said, the goal is to present
some well-defined multiple sets of interfaces to a single class so that
the compiler can limit a client's access appropriately - much the way a
standard connector in a hardware system prevents inadvertant access to
internals, while allowing for my than one kind of client.

I really believe that there is value in this, but I'm not sure what the
appropriate solution should be... oh well, I'll come back to it if I think
of something useful.
------------------------------------------------------------------------
Russell Gold                     | "... society is tradition and order
russgold@netaxs.com (preferred)  | and reverence, not a series of cheap
russgold@aol.com                 | bargains between selfish interests."
russgold@boeing.com              |




Author: maxtal@Physics.usyd.edu.au (John Max Skaller)
Date: Fri, 17 Feb 1995 13:21:14 GMT
Raw View
In article <9502151658.AA14730@phoney.he.boeing.com>,
Russ Gold <russgold@boeing.com> wrote:
>"friend" access in C++ is intended to make members of a class
>available to a selected group of potential clients, and thus improves
>information hiding by not requiring all of the internals of a class to
>be exposed to the world when some of them are required by another
>class or function which is tightly coupled; however, it still seems
>too broad, as the friend (and all of its subclasses, if it is a
>class),

 No, not any derived classes. Only the named class has access.

>can then access *everything.* It is very common that only a
>subset of the members are germane to a particular client. I therefore
>propose a modification to the "friend" concept.

 No point. The problem applies to members too.
Many members only need access to some of the class.

--
        JOHN (MAX) SKALLER,         INTERNET:maxtal@suphys.physics.su.oz.au
 Maxtal Pty Ltd,
        81A Glebe Point Rd, GLEBE   Mem: SA IT/9/22,SC22/WG21
        NSW 2037, AUSTRALIA     Phone: 61-2-566-2189




Author: bvej18@phoney.boeing.com (Russ Gold)
Date: 15 Feb 1995 11:05:36 -0600
Raw View
"friend" access in C++ is intended to make members of a class
available to a selected group of potential clients, and thus improves
information hiding by not requiring all of the internals of a class to
be exposed to the world when some of them are required by another
class or function which is tightly coupled; however, it still seems
too broad, as the friend (and all of its subclasses, if it is a
class), can then access *everything.* It is very common that only a
subset of the members are germane to a particular client. I therefore
propose a modification to the "friend" concept.

class Server {
  friend class ClientA:
    aRoutineNeededByClientsAandB;
    aRoutineNeededOnlyByClientA;

  friend class ClientB:
    aRoutineNeededByClientsAandB;

  public:
    Server();

    :

  private:
    void aRoutineNeededByClientsAandB();
    void aRoutineNeededOnlyByClientA();
    void aRoutineUsedByServerOnly();
    };

With this scheme, class ClientA can access both
"aRoutineNeededByClientsAandB" and "aRoutineNeededOnlyByClientA" as
well as all of the public members, while ClientB can access
"aRoutineNeededByClientsAandB" and the public members.  Neither,
however, can access "aRoutineUsedByServerOnly."

The current syntax for friends would retain its meaning, but the more
restricted syntax would be preferable.

This would allow classes to continue to hide internal details - even
from their "friends," and to present multiple interfaces to their
potential clients.

+-------------------------+-----------------------------------------+
| Russ Gold               |     phone: (610) 591-4220               |
| Boeing Helicopters IMS  |     email: russgold@boeing.com          |
| P.O. Box 16858          +-----------------------------------------+
| Philadelphia, PA 19142  | The opinions expressed here are my own; |
| M/S P28-24              | concurrence is always welcome...        |
+-------------------------+-----------------------------------------+