c++ 无法访问受保护成员[重复]

dbf7pr2w  于 2023-01-14  发布在  其他
关注(0)|答案(5)|浏览(260)
    • 此问题在此处已有答案**:

cannot call base class protected functions?(1个答案)
4小时前关门了。
我不明白下面的问题,当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?
}
eblbsuwk

eblbsuwk1#

一个常见的误解。
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
}
ni65a41a

ni65a41a2#

您正好碰到了标准中的一条特殊规则:

11.5受保护的成员访问

当派生类的友元或成员函数引用基类的受保护的非静态成员函数或受保护的非静态数据成员时,除了前面第11条中描述的访问检查外,还要进行访问检查。除了形成指向成员的指针外,* 访问必须通过指向派生类本身(或从该类派生的任何类)的指针、引用或对象进行。
此附加访问检查的一个原因是关于那些基类受保护成员的行为。由于成员是受保护的,不同的派生类可向这些派生成员的含义添加语义或甚至对其进行大规模改变。(这就是为什么受保护的数据相当危险的原因之一。)因为您的类没有注意到这些添加/在其他派生类中对基类语义所做的修改时,最好的做法是在访问将通过基类时阻止对基类成员的访问。

vm0i2vca

vm0i2vca3#

提供其他人所说的具体例子:

class Base {
protected:
  int x;
};

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

int main() {
  Base fiddle;
  Derived fast, furious;
  fast.foo(&furious, &fiddle);
}

void Derived::foo(Derived *d, Base* b) {
  x = 1;       // Legal, updates fast.x
  this->x = 2; // Legal, updates fast.x
  d->x = 3;    // Legal, updates furious.x
  b->x = 4;    // Error, would have updated fiddle.x
}
6ioyuze2

6ioyuze24#

您的想法是正确的,但是没有正确使用受保护成员。
void foo(Base* b)应改为void foo();
其实施将是:
::foo(){返回这个-〉x;}
因为x是一个受保护的成员,你不能从另一个对象访问它--即使那个对象继承自那个类,你只能从派生对象本身访问它。

jgwigjjp

jgwigjjp5#

你所做的实际上是创建了一个base的示例,它与derived的关系不同于derived内部的base的内部示例。将变量设置为protected会让继承类访问它自己的base的内部示例。然而,在类中创建一个base类型的对象是不同的,因此,不允许访问。

相关问题