无法访问受保护的成员

par*_*c84 17 c++ inheritance

可能重复:
无法调用基类保护函数?

我不理解以下内容,当Derived继承自Base它时,它可以访问可以通过派生函数访问的受保护成员.但是,如果Base类试图从Derived类(它本身允许访问Base)访问自己的成员,它不能访问,为什么?

class Base {
protected:
    int x;
};

class Derived : Base {
public:
    void foo(Base* b);
};


void Derived::foo(Base* b) {
    b->x = 2;       // cannot access protected member,
                    // though Derived inherits from Base, why?
}
Run Code Online (Sandbox Code Playgroud)

Ker*_* SB 14

一个常见的误解.

在里面Derived::foo(),您可以访问类对象的受保护基础成员Derived.然而,*b不是类型Derived.相反,它是类型的Base,所以它与你的类没有任何关系.

如果你把一个Derived*参数作为一个论点是另一回事- 那么你确实可以访问受保护的基础成员.


我们来拼出来吧:

struct Derived;

struct Base
{
  int f(Derived *);
protected:
  int x;
private:
  int y;
};

struct Derived : public Base
{
  int g(Base *);
  int h(Derived *);
};

int Derived::g(Base * b)
{
   return b->x; // error, protected member of unrelated class
   return b->y; // error, private member of different class
}

int Derived::h(Derived * d)
{
  return d->x;  // OK, protected base member accessible in derived class
  return d->y;  // error, private member of different class
}

int Base::f(Derived * d)
{
  return d->x;  // OK, d converts to Base*
  return d->y;  // OK, ditto
}
Run Code Online (Sandbox Code Playgroud)


Dav*_*men 6

你按照标准中的特殊规则进行了轻击:

11.5受保护的成员访问
当派生类的朋友或成员函数引用受保护的非静态成员函数或受保护的基类的非静态数据成员时,除了前面第11章中描述的那些之外,还应用访问检查.除非形成指针对于member,*访问必须通过指向,引用或派生类本身的对象(或从该类派生的任何类).

此添加访问检查的一个原因是关于这些基类保护成员的行为.由于成员受到保护,因此不同的派生类可以添加语义,甚至可以对这些派生成员的含义进行批量更改.(这是受保护数据相当危险的原因之一.)因为您的类忽略了对其他派生类中所做的基类语义的这些添加/修改,所以最好的做法是阻止对基类成员的访问.访问将通过基类.