From: matt@askinc.ask.COM (Matthew Rabuzzi)
Newsgroups: comp.lang.c++
Subject: Re: question about class member access rules, A CLARIFICATION
Date: 7 Apr 92 22:11:07 GMT
Organization: ASK Computer Systems, Inc.

On 3 Apr 92 15:11:04 GMT, hira@walkman2.bellcore.com wrote:

> I made an error in my previous posting enquiring about C++ access rules.
> Here's the corrected query (with further clarifications):
> 
> Consider the following declarations:
> 
>      class B {
>          protected:
>              int i;
>          public:
>              void foo();
>      };
> 
>      class D : public B {
>          public:
>              void bar();
>      };
> 
>      void B::foo()
>      {
>          B b;
> 
>          i = 1;    // o.k.; i is protected member of B and i == this->i
>          b.i = 1;  // LEGAL, eventhough b.i != this->i
>      }
> 
>      void D::bar()
>      {
>          B b;
> 
>          i = 1;   // o.k., as i is an inherited protected member and
>                   // i == this->i
> 
>          b.i = 1; // ILLEGAL; i is protected but b.i != this->i
>      }
> 
> Why is the second assignment in B::foo legal when the second assignment 
> in D::bar is not? Both g++ and cfront flag the latter as an error, but 
> do not complain about the former.
> 
> If the rule simply says "any member function of a class can access 
> the protected members of its base classes" then the second assignment in 
> D::bar should also be legal.
> 
> If the rule also requires that the object whose protected members are
> being accessed should be same as `*this' then the second assignment in
> B::foo should also be considered illegal!

Here is the general rule:
A member function of any class
has access to all members of objects of the same class
(whether these objects are (*this), explicit function parms, local or 
global variables is irrelevant), 
and access to _only_ public members of objects of all other classes in scope.
This is why B::foo() compiles -- i and b.i are members of objects of class B.
Note that this would be legal as well:
    void D::foo()
    {
	D d;
	i = 1;   // LEGAL; member of an object of same class as this function
	d.i = 1; // LEGAL; member of an object of same class as this function
    }

Here is an enhanced definition:
"Objects of other classes in scope" includes objects of any superclasses of 
the class of the function; these objects do not fill the "is-a" relation
with the class of the function.
Thus in D::bar(), 
access to i is legal because i is a member of an object of the same class 
as the member function (D),
but access to b.i is illegal because b.i is a member of an object of
an "other class" (B) that is not the member function's class (D).
That is, "B is-NOT-a D", so D::bar() cannot access directly any purely-B object.

Further definition:
"Objects of the same class" includes objects of any subclasses of 
the class of the function.
Thus, this is legal:
    void B::bar()
    {
	D d;
	i = 1;        // LEGAL; member of an object of same class as this func
	d.i = 1;      // LEGAL; D "is-a" B
	((B)d).i = 1; // LEGAL; member of an object of same class as this func
    }

Here is the exception to the pronouncements above, for completeness:
The restriction to "_only_ public members of objects of all other classes"
can be relaxed by making the member function a friend of some other class X;
then the function has access to all members of objects of that other class X
as well.

ObQuote: "Derivation is not friendship." -- Stanley B. Lippman, somewhere is his book