使用指向派生类中的基类的指针访问受基类保护的成员

Access base class protected members using pointers to base class in derived class

本文关键字:基类 访问 指针 成员 保护 派生      更新时间:2023-10-16

请考虑以下代码:

#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;
}

似乎可以使用指针直接访问基类的成员this但不能使用其他指针访问。
编译器是否将它们视为不同的实例化?

是的,这是预期行为。基类的受保护成员可以在派生类中访问,但只能通过派生类(或当前派生类的进一步派生类)类型的对象(包括this)。这意味着无法通过指向基类的指针访问受保护的成员。

只能访问类 Base 的受保护成员

1) ...

2)由从Base派生的任何类的成员,但仅在以下情况下 对派生自 Base 类型的对象进行操作(包括 这)

一个更简单的测试示例:

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; }
};

在派生类D2中,我们可以在D2实例中访问Base::i,但不能在Base实例中访问,也不能在派生自Base的对象中访问D2而不是通过 。

其他好的[C++参考][受保护]说:

Base的受保护成员可以被派生自Base的任何类的成员访问,但只有在对派生自Base(包括this)类型的对象进行操作时。

上面的测试表明,那里的措辞有点不准确¹ - 它应该读作"仅在对自己类型的对象或从它派生的对象进行操作时"。


¹ 或者 GCC 不正确 - 我们真的应该检查这方面的标准。