Consider the following code:
#include <iostream>
using std::endl;
using std::cout;
template<typename T>
class B{
protected:
T value;
B* ptr;
public:
B(T t):value(t), ptr(0){}
};
template<typename T>
class D: public B<T>{
public:
void f();
D(T t):B<T>(t){}
};
template<typename T>
void D<T>::f(){
cout << this->value << endl; //OK!
this->ptr = this;
cout << this->ptr->value << endl; //error! cannot access protected member!!
B<T>* a = this;
cout << a->value <<endl; //error! cannot access protected member!!
}
int main(){
D<double> a(1.2);
a.f();
return 0;
}
It seems that the member of the base class can be directly accessed using this
pointer, but not the other pointers.
Does the compiler consider them as different instantiation?
Yes, this is expected behavior. Protected members of base class can be accessed in the derived class, but only via an object of a type that is the derived class (or the further derived class of current derived class) (including
this
). That means you can't access protected members via a pointer to base class.A simpler test example:
In the derived class
D2
, we can accessBase::i
in aD2
instance, but not in aBase
instance, nor in an object that derives fromBase
not throughD2
.The otherwise-good [C++ Reference][protected] says:
The test above suggests that the wording is slightly inaccurate there¹ - it should read "only when operating on an object of its own type or one derived from it".
¹ or that GCC is incorrect - we should really check the standard for this.