T.R | Title | User | Personal Name | Date | Lines |
---|
3514.1 | protected member access rules | DECC::J_WARD | | Tue Mar 25 1997 17:02 | 13 |
|
p. 568 of Stroustrup's "C++ Programming Language, second edition":
A friend or a member function of a derived class can access a protected
nonstatic member of one of its base classes only through a pointer to,
reference to, or object of the derived class (or any class derived
from that class).
In your example,
Foo::bar() is using the implicit this pointer (a pointer of the derived class)
X.bar() is using a Foo object, which is not of the derived class
|
3514.2 | Be friends with your descendants | DECCXX::RMEYERS | Randy Meyers | Wed Mar 26 1997 18:31 | 31 |
| Re: .0
If you really want your derived classes to be able to access the protected
(and private) members of the base class through a pointer to the base class,
you can make the derived class a friend:
class Foo1; // New line -- Forward reference to Foo1
class Foo {
friend class Foo1; // New line -- Make derived class a friend
protected:
virtual int bar(void) const {return 1;}
};
class Foo1 : public Foo {
protected:
virtual int bar(void) const;
};
int Foo1::bar(void) const
{
const Foo X;
if (1) {
return Foo::bar();
}
else {
return X.bar();
}
}
This might not be the best idea in the world, however.
|
3514.3 | Okay, then why is this allowed? | TLE::LUCIA | http://asaab.zko.dec.com/~lucia/biography.html | Tue Apr 01 1997 14:08 | 41 |
| I went the 'friend' route for a while. It bothered me so much, I came up with
the following. It kind of defeats the whole rule in the first place, although
it is a maintenance headache. Why is the following allowed if the former is not?
#include <iostream.h>
class Foo {
protected:
virtual int joe(void) const { cout << "Foo::joe(void)" << endl; return 1;}
virtual int joe(Foo* f) const { cout << "Foo::joe(Foo*)" << endl; return
f->joe();}
};
class Foo1 : public Foo {
protected:
virtual int joe(void) const;
virtual int joe(Foo* f) const { cout << "Foo1::joe(Foo*)" << endl; return
Foo::joe(f);}
public:
int pubmem(void) const { return joe(); }
};
int Foo1::joe(void) const
{
cout << "Foo1::joe(void)" << endl;
Foo X;
if (1) {
return Foo::joe();
}
else {
return joe(&X);
}
}
int main()
{
Foo1 aFoo1;
cout << "aFoo1.pubmem() = " << aFoo1.pubmem() << endl;
return 0;
}
|
3514.4 | | SPECXN::DERAMO | Dan D'Eramo | Tue Apr 01 1997 14:46 | 53 |
| All of the calls to joe in any of the derived class (Foo1)
member functions either call the dervied class's joe or call
the base class's (Foo's) joe via the "this" pointer to a
derived class object. So they are all legal.
Dan
class Foo1 : public Foo {
protected:
virtual int joe(void) const;
virtual int joe(Foo* f) const { cout << "Foo1::joe(Foo*)" << endl; return
Foo::joe(f);}
// no reason for the above to fail; Foo::joe(Foo *) is
// accessed through the derived class pointer "this"
public:
int pubmem(void) const { return joe(); }
// no reason for the above to fail, Foo1 can access Foo1::joe(void)
};
int Foo1::joe(void) const
{
cout << "Foo1::joe(void)" << endl;
Foo X;
if (1) {
return Foo::joe();
// no reason for the above to fail; Foo::joe(Foo *) is
// accessed through the derived class pointer "this"
}
else {
return joe(&X);
// no reason for the above to fail, Foo1 can access Foo1::joe(Foo *)
}
// these would be illegal though
// X.joe(); // illegal -- Foo::joe(void) accessed not through a Foo1
// Foo *p = &X;
// p->joe(); // illegal -- Foo::joe(void) accessed not through a Foo1
}
int main()
{
Foo1 aFoo1;
cout << "aFoo1.pubmem() = " << aFoo1.pubmem() << endl;
return 0;
}
|
3514.5 | | TLE::LUCIA | http://asaab.zko.dec.com/~lucia/biography.html | Tue Apr 01 1997 17:43 | 3 |
| I understand why this particular example works. What I don't understand is the
reasoning behind the first one not working. I.e., "Bjarne, what were you
thinking?"
|
3514.6 | | SPECXN::DERAMO | Dan D'Eramo | Tue Apr 01 1997 18:48 | 31 |
| Without the restriction protected access would be meaningless.
Anyone would be able to call protected non-static member
functions...
#include "ClassX.h"
class Hack : public ClassX {
public:
void bypass(ClassX &x) { x.protected_member_function(); }
};
int main()
{
ClassX x;
// x.protected_member_function(); // illegal
Hack h;
h.bypass(x); // heh heh heh ... oops, Bjarne says no
return 0;
}
The restriction means that a legitimate derived class can
still use the base class's protected member functions on its
own instances. It just can't be used to bypass access
checking on other objects not of the derived class.
Dan
|