masotti@usc.edu (Glauco Masotti) (07/18/89)
I had some problems using protected members. I was pretty confident, after reading the "evolution paper" from Bjarne, that my files would compile, but I received instead complains from the compiler. I am using g++, 1.35.0+, so I first thought of a bug in the compiler and I wrote to the FSF. I kept exchanging mail with Doug Lea. He told me I should be right, and that he also would like protected to work the way I used them, but that this doesn't conform to AT&T 2.0 specs. The interpretation of the evolution paper seems therefore to be cumbersome, but he also told me to have discussed the matter with Bjarne himself, to be sure of his interpretation. The following is the example: --------------------------------------- #include <stream.h> struct A { A(int i) {j=i;} void increment() {j++;} print() {cout<<j<<"\n";} protected: int j; }; struct B : A { int k; A* a; B(int i, int j, A* x) : A(i) {k=j; a=x;} print() {cout<<j<<" "<<k<<" "<<a->j"\n";} }; main() { int i=9; A a(i); a.increment(); a.print(); B b(2, 3, &a); b.print(); } ------------------------------------------------ Here a protected member of a class is accessed through a pointer in a member function of a derived class. To me this should be allowed, I find pretty counterintuitive the contrary. I would like to know what people think. If Andrew or Bjarne are listening I would appreciate very much their response. In any case if I cannot write something like the previous example, I think the cases where the protection mechanism will help instead of being a burden will shrink significantly. Therefore the problems protected was intended to solve (as reported in the evolution paper) will not be solved and we will be forced to resort again to public everything or make a lot of friends (which in C++ is not as good as in life :-)). -Glauco Masotti masotti@lipari.usc.edu P.S. This is my first posting, so... Hello to everybody! You may here from me again if I keep working on my current project.
ark@alice.UUCP (Andrew Koenig) (07/18/89)
In article <MASOTTI.89Jul17110844@lipari.usc.edu>, masotti@usc.edu (Glauco Masotti) writes: > I had some problems using protected members. I was pretty confident, after > reading the "evolution paper" from Bjarne, that my files would compile, but I > received instead complains from the compiler. Rather than jumping into your example right away, let's look at a simpler one. class X { protected: int x; }; The idea of `protected' is to nominate parts of a class that may only be used as scaffolding on which to build derived classes. Thus, for example, the following is legal: class Y: public X { public: void zot() { x = 0; } }; because, although Y::zot() appears to be clobbering X::x, in fact it does so only in its capacity as a part of a Y. For instance, suppose we change the definition of Y: class Y: public X { public: void zot() { x = 0; } void clear(X& xr) { xr.x = 0; } }; We then get a message that Y::clear() cannot access X::x, because xr.x is a member of a plain old X, not an X that's known to be part of a Y. Although this treatment seems counterintuitive at first, there are several reasons for it. First, if C++ did not restrict things this way, anyone could circumvent protection for any protected member of any object merely by deriving a dummy class as shown above. Second, it is quite easy to make things less restrictive if that's what you want: in this example, for instance, you could make Y a friend of X or make X::x public. It is much harder to make things more restrictive. Most of us who have grappled with this problem have found that there's often a way of doing what we want without running afoul of the protection restrictions. The solution, once found, may well be cleaner than the original version. Try it and see. -- --Andrew Koenig ark@europa.att.com
sakkinen@tukki.jyu.fi (Markku Sakkinen) (07/21/89)
In article <MASOTTI.89Jul17110844@lipari.usc.edu> masotti@usc.edu (Glauco Masotti) writes: >I had some problems using protected members. I was pretty confident, after >reading the "evolution paper" from Bjarne, that my files would compile, but I >received instead complains from the compiler. I am using g++, 1.35.0+ ... > ... >The following is the example: > ... > >Here a protected member of a class is accessed through a pointer in a member >function of a derived class. >To me this should be allowed, I find pretty counterintuitive the contrary. >I would like to know what people think. If Andrew or Bjarne are listening I >would appreciate very much their response. The essence of Masotti's example compiled all right under release 1.2 (Glockenspiel's Designer C++); I just had to edit a couple of other details. However, checking in Stroustrup's "evolution paper" from the USENIX C++ Workshop 1987, I found a rather clear statement to the contrary on p. 3: "A member or a friend of a derived class has access only to protected members of objects that are known to be of its derived type." (***) (see below) >In any case if I cannot write something like the previous example, I think the >cases where the protection mechanism will help instead of being a burden will >shrink significantly. Therefore the problems protected was intended to solve (as >reported in the evolution paper) will not be solved and we will be forced to >resort again to public everything or make a lot of friends (which in C++ is >not as good as in life :-)). > >-Glauco Masotti > >masotti@lipari.usc.edu In article <9630@alice.UUCP> ark@alice.UUCP (Andrew Koenig) writes: > ... >The idea of `protected' is to nominate parts of a class that may >only be used as scaffolding on which to build derived classes. > ... > >Although this treatment seems counterintuitive at first, there >are several reasons for it. > >First, if C++ did not restrict things this way, anyone could >circumvent protection for any protected member of any object >merely by deriving a dummy class as shown above. This argument is valid, but not yet overwhelming: there are so many means to circumvent all kinds of protection in C++ anyway. >Second, it is quite easy to make things less restrictive if >that's what you want: in this example, for instance, you could >make Y a friend of X or make X::x public. It is much harder >to make things more restrictive. This suggestion is exactly what Masotti protested against under (***)! >Most of us who have grappled with this problem have found that >there's often a way of doing what we want without running afoul of >the protection restrictions. The solution, once found, may >well be cleaner than the original version. Try it and see. This sounds like the Oracle of Delfoi (Delphi) - leaves me puzzled. If it means e.g. that one should sometimes add more public functions to the base class than have originally been defined, to allow the orderly handling of some private or protected variables, I can agree. >-- > --Andrew Koenig > ark@europa.att.com There are more reasons than (***) why it could be recommendable to allow a member or friend function of a derived class to access protected "members" (I do dislike the meaning given to the word 'member' in C++ literature) of base class objects: 1. Encapsulation in C++ is otherwise on the level of _classes_, as opposed to Smalltalk (every object encapsulated from all others) and Simula (no encapsulation); this would be more analogous. 2. The rules for protected parts would be a little simpler. 3. It would be compatible with earlier versions of C++ (as noted in the beginning of this posting). However, interpreting 'protected' like this would logically require that one could declare something similar to friend classes and functions, i.e. access rights to protected members for some others beside derived classes. Perhaps 'cousin' would do - although I have claimed to oppose to anthropomorphic terminology. See the suggestion for 'acquaintance' in my paper in SIGPLAN Notices, December 1988. Markku Sakkinen Department of Computer Science University of Jyvaskyla (a's with umlauts) Seminaarinkatu 15 SF-40100 Jyvaskyla (umlauts again) Finland
richard@pantor.UUCP (Richard Sargent) (03/20/90)
(I apologize if this has been seen before, but I have had no indication that it successfully made its way out into the world.) We have encountered a problem with C++ 2.0, and diligent reading of the manual confirms that we are wrong. :-( I am left with a couple of questions as a result, but first the problem: We have a tree of classes, such as various graphics objects. We want to have some base class members be accessible only to objects from this tree of classes. No problem you say, just use protected. There's the nub: any given object can access its protected base members, but not those of any other object derived from the same tree. (Reference: AT&T Reference Manual, Select Code 307-146, section 11.5 Protected Member Access, page 73) For example, we have a derived class which we want to be able to traverse an array of graphics objects (of which class it is, too). However, this object (and its member functions) cannot access the protected members of the objects in this array. Q1: Why was the language specified with this restriction? I am not a language designer, so I don't understand the decisions that might be obvious to some one is. I certainly don't presume to think that Stroustrup is incorrect, but I do want to understand the ratioanle here. Q2: Given that this restriction is part of the language, how can I work around it? The obvious solution is to make the member in question "public", but then everything has access to it. However, I see no alternatives. Any and all help and explanations welcomed and appreciated. Thanks in advance. Richard Sargent Internet: richard@pantor.UUCP Systems Analyst UUCP: ...!mnetor!becker!pantor!richard