Topic: what about "partial friend
Author: "Chuck Met" <newsforchuck@yahoo.com>
Date: Thu, 24 Jan 2002 09:52:49 CST Raw View
"Eric Desrosiers" <deseric@rogers.com> wrote in message
news:3C195F2A.50003@rogers.com...
> I do not know if someone mentioned something like this before :
>
> I would like a fine grain mechanism for controlling class member access :
>
A neat method might be to allow arbitrary access specifiers with "using"
indicating what access is required, eg:
class MultiAccess
{
public:
void aPublicFunction();
private:
void implementationFunction();
group1funcs:
void group1Function();
group2funcs:
void group2Function();
};
class Other
{
using MultiAccess::group2funcs;
void otherFunc1() { ma_.group1Function(); } // Illegal
void otherFunc2() { ma_.group2Function(); } // Legal
MultiAccess ma_;
};
int main()
{
MultiAccess ma;
ma.group1Function(); // Illegal
{
using MultiAccess::group1funcs;
ma.group1Function(); // Legal
}
}
A section could also be controlled by more than one specifier:
class MultiAccess2
{
group1funcs, protected:
void group1Function(); // can be called by derived classes
// and group1funcs classes
group2funcs, group3funcs:
void group2Function(); // can be called by group1funcs classes and
// group2funcs classes but not by
derived classes
};
Could this notation be ambiguous?
--
Chuck Met
For email, put [NotSpam] somewhere in the message subject or body.
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.research.att.com/~austern/csc/faq.html ]
Author: Eric Desrosiers <deseric@rogers.com>
Date: Thu, 13 Dec 2001 20:28:50 CST Raw View
I do not know if someone mentioned something like this before :
I would like a fine grain mechanism for controlling class member access :
To control access in a multithreaded program, I often end up writing a
class holding the data accessed and another class to control the access.
What I do is make all the member accessor the data class(D) protected
or private and make my access(A) class friend of D.
This always feel weird to me because then I give A access to all the
concrete data of D. Of course I could another layer, but it would be
nice to be able to define which class(es) can access which functions in
another. That why I call that partial friend.
To ease the development, we could define groups and users just like in
Unix.
People have argued with me that it would be a pain to write all those
partial friend definitions, but I respond by saying that in my
experience, classes usually interacts only with a few other and so the
extra writing is not very heavy. It could also be automated by tools
provided by IDEs. By default, classes could just be like they are right
now and then restrictions could be added has needed.
I feel that this way, it is clear what is your intent use of the class
and so the next person who will maintain the class won't have to think
too much on how to use it.
What do you think?
Eric Desrosiers
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.research.att.com/~austern/csc/faq.html ]
Author: Adam Peterson <ahp6@email.byu.edu>
Date: Fri, 14 Dec 2001 13:24:42 CST Raw View
"Eric Desrosiers" <deseric@rogers.com> wrote in message
news:3C195F2A.50003@rogers.com...
> I do not know if someone mentioned something like this before :
>
> I would like a fine grain mechanism for controlling class member access :
>
> To control access in a multithreaded program, I often end up writing a
> class holding the data accessed and another class to control the access.
> What I do is make all the member accessor the data class(D) protected
> or private and make my access(A) class friend of D.
> This always feel weird to me because then I give A access to all the
> concrete data of D. Of course I could another layer, but it would be
> nice to be able to define which class(es) can access which functions in
> another. That why I call that partial friend.
>
> To ease the development, we could define groups and users just like in
> Unix.
>
> People have argued with me that it would be a pain to write all those
> partial friend definitions, but I respond by saying that in my
> experience, classes usually interacts only with a few other and so the
> extra writing is not very heavy. It could also be automated by tools
> provided by IDEs. By default, classes could just be like they are right
> now and then restrictions could be added has needed.
>
> I feel that this way, it is clear what is your intent use of the class
> and so the next person who will maintain the class won't have to think
> too much on how to use it.
>
> What do you think?
>
I think the way to make your intentions clear is to provide thorough
documentation for your class. This is more than sufficient for this type of
thing and involved access schemes are much less than sufficient.
What it boils down to is: do you trust the class you are granting friendship
to or not? If you trust it and the developer who writes it (perhaps because
you are that developer) to maintain your abstract interface, full friendship
is appropriate. If you don't trust it, any friendship (access to protected
and private members) is a hole in encapsulation.
The rationale for the user/group system in Unix is different in principle.
You grant permission for limited, consistent access to services to
semi-trusted agents in an effort to minimize damage in the event of a
malicious user, and you administer and monitor it very tightly to prevent
breaches. In C++, you can almost always circumvent protection (often by
invoking undefined behavior which you happen to know the consequences of in
a given implementation), and once the class is written and test it, you
almost never monitor it, except during maintenance. You almost never
monitor its usage. Extra mechanisms to grant multiple tiers of access is
extra work that isn't necessary. Security is not the issue. Good design
principles are the issue, and the good design principle is to grant
friendship only to classes who share in the responsibility to maintain the
abstract interface of your class.
I must confess that I've thought about this possibility myself with some
fascination, but when I think about it in terms of core design and software
engineering considerations (which are primarily what data hiding is there to
facilitate), I have to conclude that partial friendship is not a core
software engineering tool. If you really think your design is better with
it, you probably need to split your class into more than one class, use
aggregation, and grant friendship to that member class only. (Remember,
friendship is not transitive.)
Also, remember that when it comes to the interface between your class and
the rest of the system, documentation is essential for both making up for
perceived limitations in the expressive power of the language and just plain
sane use of your class. Use it liberally.
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.research.att.com/~austern/csc/faq.html ]
Author: "David Yasko" <nospam@nospam.com>
Date: Fri, 14 Dec 2001 13:24:45 CST Raw View
Have you thought about wrapping your base class in other classes that only
expose those base class member functions that each kind of friend can
access? Something like the following:
class CBaseClass {
protected:
function1();
function2();
function3();
};
class CDerivedClass1 : proctected CBaseClass {
public:
function1(){CBaseClass::function1();}
function3(){CBaseClass::function3();}
};
class CDerivedClass2 : proctected CBaseClass {
public:
function2(){CBaseClass::function2();}
function3(){CBaseClass::function3();}
};
There may be some issues with the "public" and "protected" keywords to get
things just the way you want, but it should give you the access you want. I
almost always use "public" sub-classing, with all of the member functions
"public", and data members "protected", so I am basically guessing here. I
hope this gives you something to think about.
Good luck.
--
David Yasko
"The day after tomorrow is the third day of the rest of your life."
"Eric Desrosiers" <deseric@rogers.com> wrote in message
news:3C195F2A.50003@rogers.com...
: I do not know if someone mentioned something like this before :
:
: I would like a fine grain mechanism for controlling class member access :
:
: To control access in a multithreaded program, I often end up writing a
: class holding the data accessed and another class to control the access.
: What I do is make all the member accessor the data class(D) protected
: or private and make my access(A) class friend of D.
: This always feel weird to me because then I give A access to all the
: concrete data of D. Of course I could another layer, but it would be
: nice to be able to define which class(es) can access which functions in
: another. That why I call that partial friend.
:
: To ease the development, we could define groups and users just like in
: Unix.
:
: People have argued with me that it would be a pain to write all those
: partial friend definitions, but I respond by saying that in my
: experience, classes usually interacts only with a few other and so the
: extra writing is not very heavy. It could also be automated by tools
: provided by IDEs. By default, classes could just be like they are right
: now and then restrictions could be added has needed.
:
: I feel that this way, it is clear what is your intent use of the class
: and so the next person who will maintain the class won't have to think
: too much on how to use it.
:
: What do you think?
:
: Eric Desrosiers
:
:
: ---
: [ comp.std.c++ is moderated. To submit articles, try just posting with ]
: [ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
: [ --- Please see the FAQ before posting. --- ]
: [ FAQ: http://www.research.att.com/~austern/csc/faq.html ]
:
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.research.att.com/~austern/csc/faq.html ]
Author: Steve Clamage <clamage@eng.sun.com>
Date: Fri, 14 Dec 2001 16:07:57 CST Raw View
On Thu, 13 Dec 2001, Eric Desrosiers wrote:
> I do not know if someone mentioned something like this before :
>
> I would like a fine grain mechanism for controlling class member access :
Yes, this question comes up frequently.
In my opinion, wanting fine-grained access control means you have
lost control of your code. Probably your class decomposition is
too large-grained.
--
Steve Clamage, stephen.clamage@sun.com
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.research.att.com/~austern/csc/faq.html ]
Author: Marc Girod <girod@stybba.ntc.nokia.com>
Date: Sat, 15 Dec 2001 08:51:20 CST Raw View
>>>>> "ED" == Eric Desrosiers <deseric@rogers.com> writes:
ED> What do you think?
That this would better be served by supporting fine-grained multiple
inheritance.
I.e. I agree with you to want and use friendship to control access,
and to want to do so at arbitrarily fine grain.
Now, I believe this should stay at the level of classes, and not go
below. The resolution is that one should support the composition of
arbitrarily small classes. This supposes virtual inheritance and
breaks in the huge costs implied so far.
--
Marc Girod P.O. Box 370 Voice: +358-71 80 25581
Nokia NBI 00045 NOKIA Group Mobile: +358-50 38 78415
Karaportti 2 Finland Fax: +358-71 80 66204
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.research.att.com/~austern/csc/faq.html ]
Author: "Bo-Staffan Lankinen" <bo_steffan_lankinen@hotmail.com>
Date: Sun, 16 Dec 2001 13:28:11 CST Raw View
> Of course I could another layer,
There are, for instance, situations when one can't afford to pay the price,
both in executionspeed and memory footprint, of using an abstract interface.
> What do you think?
There are definately situations where fine-grined access control can improve
the robustness of classes without imposing an unnecessary layer of
abstraction, which will cost resources both in executionspeed and memory
footprint. IMO, it violates the fundamental concept of C++, ie. that you
don't pay for what you don't use, because one is forced to use polymorphism
when one shouldn't have to.
One could argue that the need of fine-grained access control is a sign of
bad design, using bloated interfaces. Indeed it can be so but it doesn't
have to be so and that's a big difference. In my current project, I've a
concrete example of small classes, representing geometry ie.
vertices,edges,patches and volumes, that suffer from not having fine-grained
access control. Each geometry class of dimension N is related to the
geometry classes with dimension N-1 and N+1, which means the private
interface is split in three parts, one part for the implementation of the
class and two parts for interfacing with classes of dimension N-1 and N+1. I
haven't, inadvertely, invoked any function in the private interface of the
classes of dimension N-1 or N+1 from the class of dimension N yet, but it's
a ticking bomb and eventually I'll probably do so. This matter will be even
more pressing when there are more people involved in a project.
Bo-Staffan
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.research.att.com/~austern/csc/faq.html ]
Author: "Bill Wade" <wrwade@swbell.net>
Date: Mon, 17 Dec 2001 15:52:09 GMT Raw View
"Eric Desrosiers" <deseric@rogers.com> wrote in message
news:3C195F2A.50003@rogers.com...
> I would like a fine grain mechanism for controlling class member access :
There are various ways to accomplish this using variations of
template<class T> class credentials
{
credentials(){} // Only T can create credentials<T>
friend T;
};
class A;
struct D
{
// Only A can create the credentials needed to call AFunc
static void AFunc(const credentials<A>&);
};
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.research.att.com/~austern/csc/faq.html ]