Possible Duplicate:
Accessing protected members in a derived class
If I have an abstract base class and a concrete templated class that derives from it, which has a method that uses a pointer to the base class - it seems that the derived class stops seeing itself as derived from it:
class AbstractBase
{
protected:
virtual void test() = 0;
};
template < class T >
class Derived : public AbstractBase
{
public:
virtual void call( AbstractBase* d ) { d->test(); } // Error!
protected:
virtual void test() {}
};
int main()
{
Derived< int > a;
Derived< int > b;
b.call( &a );
return EXIT_SUCCESS;
}
This errors with:
'virtual void AbstractBase::test()' is protected
The compiler's not wrong, it's definitely protected - but if Derived< T > inherits from AbstractBase, why is it complaining?
The reason it isn't allowed is because AbstractBase as a type declares test to be protected. This makes it private to all unless the current class is a direct descendant of AbstractBase. Even so, that class can only access the member though an object of the same class, not a different descendant, and not directly from AbstractBase itself.
template < class T >
class Derived : public AbstractBase
{
public:
virtual void call( Derived * d ) {
d->test(); // ok, d has same type as this
AbstractBase *b = this;
b->test(); // not ok
}
protected:
virtual void test() {}
};
You can, as demonstrated above, just allow it for pointers of the same type. Alternatively, you can create a proxy base class for Derived to implement your virtual method to call test. This will allow access from different Derived types.
class DerivedBase : public virtual AbstractBase
{
public:
virtual void call( DerivedBase * d ) { d->test(); }
};
template < class T >
class Derived : public DerivedBase
{
protected:
virtual void test() {}
};
And can be accessed this way:
Derived< int > a;
Derived< int > b;
Derived< float > c;
b.call( &a );
c.call( &a );
This is not related to templates, but to protected member access in general. See section 11.4 Protected member access [class.protected] of the latest publicly available draft C++ Standard
An additional access check beyond those described earlier in Clause 11 is applied when a non-static data member or non-static member function is a protected member of its naming class (11.2) 115 As described earlier, access to a protected member is granted because the reference occurs in a friend or member of some class C. If the access is to form a pointer to member (5.3.1), the nested-name-specifier shall denote C or a class derived from C. All other accesses involve a (possibly implicit) object expression (5.2.5). In this case, the class of the object expression shall be C or a class derived from C.
[Example:
class B {
protected:
int i;
static int j;
};
class D1 : public B {
};
class D2 : public B {
friend void fr(B*,D1*,D2*);
void mem(B*,D1*);
};
void fr(B* pb, D1* p1, D2* p2) {
pb->i = 1; // ill-formed
p1->i = 2; // ill-formed
p2->i = 3; // OK (access through a D2)
p2->B::i = 4; // OK (access through a D2, even though
// naming class is B)
int B::* pmi_B = &B::i; // ill-formed
int B::* pmi_B2 = &D2::i; // OK (type of &D2::i is int B::*)
B::j = 5; // OK (because refers to static member)
D2::j = 6; // OK (because refers to static member)
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With