Access base class protected members using pointers

2019-03-01 13:26发布

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?

2条回答
一纸荒年 Trace。
2楼-- · 2019-03-01 13:58

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 protected member of a class Base can only be accessed

1) ...

2) by the members of any class derived from Base, but only when operating on an object of a type that is derived from Base (including this)

查看更多
我命由我不由天
3楼-- · 2019-03-01 14:03

A simpler test example:

class Base
{
protected:
    int i;
};

class D1 : public Base
{
};

class D2 : public Base
{
    int a(Base& b) { return b.i; } // error
    int a(D1& d) { return d.i; }   // error

    int a(D2& d) { return d.i; }
};

In the derived class D2, we can access Base::i in a D2 instance, but not in a Base instance, nor in an object that derives from Base not through D2.

The otherwise-good [C++ Reference][protected] says:

A protected member of a class Base can be accessed [...] by the members of any class derived from Base, but only when operating on an object of a type that is derived from Base (including this).

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.

查看更多
登录 后发表回答