Доступ к защищенным членам в производном классе - PullRequest
53 голосов
/ 14 июля 2010

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

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

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.Мне кажется, что при использовании открытого наследования защищенные переменные все еще видны производному классу.

Ответы [ 7 ]

40 голосов
/ 14 июля 2010

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

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

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

4 голосов
/ 14 июля 2010

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

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

class Derived : public Base
{
  protected:
    int d;
  public:
    void DoSomething(const Base& that)
    {
      Base::DoSomething(that);
      d=0;
    }
};
3 голосов
/ 10 сентября 2017

protected члены могут быть доступны:

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

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

Принять Derived в Derived :: 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;
    }
};

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

3 голосов
/ 14 июля 2010

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

1 голос
/ 11 декабря 2018

Вы можете попробовать с static_cast (pBase) -> Base :: 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)->Base::b;
      d=0;
    }
    void DoSomething(const Base* that)
    {
      b += static_cast<const Derived*>(that)->Base::b;
      d=0;
    }
};
1 голос
/ 17 мая 2018
class Derived : public Base
{
  protected:
    int d;
  public:
    void DoSomething()
    {
      b+=this->b;
      d=0;
    }
};

//this will work
0 голосов
/ 23 ноября 2015

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

class Derived : public Base
{
  protected:
    int d;
  public:
    void DoSomething(const Base& that)
    {
      this->b+=that.b;
      d=0;
    }
};
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...