Подтвердить что ты не робот

Доступ к защищенным членам в производном классе

Вчера я столкнулся с ошибкой и, хотя мне было легко обойти, я хотел убедиться, что я правильно понимаю С++.

У меня есть базовый класс с защищенным членом:

class Base
{
  protected:
    int b;
  public:
    void DoSomething(const Base& that)
    {
      b+=that.b;
    }
};

Это компилируется и работает отлично. Теперь я расширяю Base, но все еще хочу использовать b:

class Derived : public Base
{
  protected:
    int d;
  public:
    void DoSomething(const Base& that)
    {
      b+=that.b;
      d=0;
    }
};

Обратите внимание, что в этом случае DoSomething все еще принимает ссылку на Base, а не Derived. Я бы ожидал, что у меня все еще будет доступ к that.b внутри Derived, но я получаю ошибку cannot access protected member (MSVC 8.0 - еще не пробовал gcc).

Очевидно, что добавление публичного getter на b решило проблему, но мне было интересно, почему я не мог получить доступ непосредственно к b. Я, однако, что, когда вы используете публичное наследование, защищенные переменные все еще видны производному классу.

4b9b3361

Ответ 1

Вы можете получить доступ только к защищенным членам в экземплярах вашего типа (или получить их из вашего типа).
Вы не можете получить доступ к защищенным членам экземпляра родительского или двоюродного типа.

В вашем случае класс Derived может получить доступ только к элементу b экземпляра Derived, а не к другому экземпляру Base.

Изменение конструктора для получения экземпляра Derived также решит проблему.

Ответ 2

У вас есть доступ к защищенным членам Derived, но не к Base (даже если это единственная причина, по которой он защищен членом Derived, потому что он унаследован от Base)

Ответ 3

Как уже упоминалось, это так, как работает язык.

Другим решением является использование наследования и переход к родительскому методу:

class Derived : public Base
{
  protected:
    int d;
  public:
    void DoSomething(const Base& that)
    {
      Base::DoSomething(that);
      d=0;
    }
};

Ответ 4

Доступ к элементам

protected:

  • через this указатель
  • или защищенным членам того же типа, даже если они объявлены в базе
  • или из классов друзей, функций

Для решения вашего дела вы можете использовать один из двух последних вариантов.

Принять Производные в Производных:: DoSomething или объявить Derived friend в Base:

class Derived;

class Base
{
  friend class Derived;
  protected:
    int b;
  public:
    void DoSomething(const Base& that)
    {
      b+=that.b;
    }
};

class Derived : public Base
{
  protected:
    int d;
  public:
    void DoSomething(const Base& that)
    {
      b+=that.b;
      d=0;
    }
};

В некоторых случаях вы также можете рассматривать публичные геттеры.

Ответ 5

class Derived : public Base
{
  protected:
    int d;
  public:
    void DoSomething()
    {
      b+=this->b;
      d=0;
    }
};

//this will work

Ответ 6

Вы можете попробовать с static_cast <const Derived *> (pBase) → protected_member...

class Base
{
  protected:
    int b;

  public:
    ...
};

class Derived : public Base
{
  protected:
    int d;

  public:
    void DoSomething(const Base* that)
    {
      b += static_cast<const Derived*>(that)->b;
      d=0;
    }
};

Ответ 7

Используйте указатель this для доступа к защищенным членам

class Derived : public Base
{
  protected:
    int d;
  public:
    void DoSomething(const Base& that)
    {
      this->b+=that.b;
      d=0;
    }
};