[comp.lang.c++] protected member functions

wkd@asc.slb.com (Bill Duttweiler) (03/15/91)

Is it illegal to call a protected member function on an instance other
than 'this'? Consider the following simple example:

class A
{
public:
    A();
protected:
    void SetState();
};

class B : public A
{
public:
    B(A* a) { MyA = a; }
    void Foo() { MyA->SetState(); }
protected:
    A *MyA;
};

When run through g++ (1.37.1), I get the following error message:

test.cc: In method void B::Foo ():
test.cc:13: method `void A::SetState ()' is protected

When run through Sun C++ (based on cfront 2.0), I get

"test.cc", line 13: error:  B::Foo() cannot access A::SetState(): protected  member

So, these compilers agree. But I don't: B is publicly derived from A
and should have access to protected member functions from within its
own member functions. I can call SetState() on 'this', why not on
MyA???
-- 
William K. Duttweiler                   Schlumberger Austin Systems Center
(512) 331-3000                          PO Box 200015
wkd@asc.slb.com                         Austin, TX  78720-0015

mittle@blinn.watson.ibm.com (Josh Mittleman) (03/16/91)

ARM, p.253, reads "A friend or member function of a derived class can
access a protected nonstatic member of base of its base classes only
through a pointer to, reference to, or object of the derived class (or any
class derived from that class)."  A discussion of this restriction can be
found on pp.254-5.

A::SetState() is a protected member of A and, by virtue of the public
derivation, B::SetState() is a protected member of B.  But they aren't the
same thing, although they have the same implementation.  Member functions
of B can access B::SetState(), but they have no access to the protected
parts of an A object; only members and friends of A can access those.

Given your original code, suppose there were some other class C : public A,
in which SetState() were overloaded:

class C : public A
{
  protected: void SetState();
};

Now, we do this:

  C objectC;
  B objectB(&C);  // C is a A, so the C* is automatically converted to A*.
  B.Foo();        // wrong: invokes C->A::SetState() instead of
                  // C->C::SetState(). 

Of course, this error could be avoided by making SetState() virtual, but it
still is an incorrect result.  
 

===========================================================================
Josh Mittleman (mittle@ibm.com or joshua@paul.rutgers.edu)
J2-C28 T.J. Watson Research Center, PO Box 704, Yorktown Heights, NY  10598

dsouza@gwen.cad.mcc.com (Desmond Dsouza) (03/16/91)

wkd@asc.slb.com (Bill Duttweiler) asks:

  >Is it illegal to call a protected member function on an instance other
  >than 'this'? Consider the following simple example:

The derived class has access to inherited protected data members
within the context of ANY object OF ITS CLASS, not just "this" (also
of further derived classes). See ARM, p. 253

class A { protected: int i; };

class B : public A {
public:
  foo (B* bp, A* ap)
	{ bp->i = 5;	// OK
	  ap->i = 5;	// ERROR: 
	}
};

-- 
Desmond.
--

-------------------------------------------------------------------------------
 Desmond D'Souza, MCC CAD Program | ARPA: dsouza@mcc.com | Phone: [512] 338-3324
 Box 200195, Austin, TX 78720 | UUCP: {uunet,harvard,gatech,pyramid}!cs.utexas.edu!milano!cadillac!dsouza

mwb@ulysses.att.com (Michael W. Balk) (03/17/91)

In article <1991Mar14.215717.28199@asc.slb.com>, wkd@asc.slb.com (Bill Duttweiler) writes:
> 
> Is it illegal to call a protected member function on an instance other
> than 'this'? Consider the following simple example:
> 
> class A
> {
> public:
>     A();
> protected:
>     void SetState();
> };
> 
> class B : public A
> {
> public:
>     B(A* a) { MyA = a; }
>     void Foo() { MyA->SetState(); }
> protected:
>     A *MyA;
> };


The problem here is that MyA is a pointer to an instance of A -- it is *not* an
instance of B.  In otherwords, MyA->SetState() is not permitted regardless
of whether Foo is a member function of class B or not.  If this were not the
case, then one could access the protected and private members of any object
simply by deriving from that object's class.  In order to access A::SetState
from an instance of class B, class B should be modified as follows:

class B : public A
{
public:
	B() {}
	void Foo() { SetState(); }
};



Since B is derived from A it already contains everything that is in A
through the derivation.  In the above definition of class B, Foo executes a
member function of the base part of the same object.  This is legal since
and instance of B is also an A.


Michael W. Balk
AT&T Bell Laboratories
Murray Hill, NJ 07974
mwb@ulysses.att.com