Topic: Access to protected inherited members
Author: sdouglass@armltd.co.uk (scott douglass)
Date: 24 Mar 1995 11:29:48 GMT Raw View
Hello,
(11.5) has the following sentence that has been added since the ARM:
"When a protected member of a base class appears in a <qualified-id> in a
friend or a member function of a derived class, the
<nested-name-specifier> must name the derived class."
I believe that this was added to prevent users from using pointers to
members to get to protected members they are not supposed to get to. And
I think this is a good goal. The example changed to show that trying to
do this is now an error.
But by using the term <qualified-id> the following code has become illegal:
struct X { protected: int f(); };
struct Y : public X { int f(); };
int Y::f() { return X::f() + 1; } // now illegal 'X::f' is a
<qualified-id>
Also previously legal was accessing protected static members using a
<qualified-id>:
struct S { protected: static int i; };
struct T : public S { int f(); };
int T::f(int i) { return i + S::i + 1; } // now illegal 'S::i' is a
<qualified-id>
Was this indended? These would remain legal if (11.5) were worded
something like:
(11.5) "When a pointer to a protected non-static member of a base class is
formed using &<qualified-id> in a friend or a member function of a derived
class, the <nested-name-specifier> must name the derived class."
This also would allow pointers to protected static members, which is
consistent with being able to access them directl. The fully fleshed-out
example would now look like:
class B {
protected:
int i;
void mem();
static int st;
};
class D1 : public B {
};
class D2 : public B {
friend void fr(B*,D1*,D2*);
mem(B*,D1*);
};
void fr(B* pb, D1* p1, D2* p2)
{
pb->i = 1; // illegal
p1->i = 2; // illegal
p2->i = 3; // ok
B::st = 4; // ok
int B::* pmi_B = &B::i; // illegal
int D2::* pmi_D2 = &D2::i; // ok
int* pi = &B::st; // ok
B::mem(pb, p1); // ok, same as 'mem()'
}
void D2::mem(B* pb, D1* p1)
{
pb->i = 1; // illegal
p1->i = 2; // illegal
i = 3; // ok (access through 'this')
B::st = 4; // ok, same as 'st = 4'
B::mem(pb, p1); // ok, same as 'mem()'
}
void g(B* pb, D1* p1, D2* p2)
{
pb->i = 1; // illegal
p1->i = 2; // illegal
p2->i = 3; // illegal
B::st = 4; // illegal
int B::* pmi_B = &B::i; // illegal
int* pi = &B::st; // illegal
pb->mem(pb, p1); // illegal
p1->mem(pb, p1); // illegal
}
--scott