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

Не удается получить доступ к защищенному члену

Возможный дубликат:
не может вызвать функции, защищенные базовым классом?

Я не понимаю следующее, когда 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?
}
4b9b3361

Ответ 1

Общее недоразумение.

Внутри 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
}

Ответ 2

Вы запускали smack dab в специальное правило в стандарте:

11.5 Доступ к защищенному члену
Когда функция друга или члена производного класса ссылается на защищенную нестатистическую функцию-член или защищенный нестатический элемент данных базового класса, проверка доступа применяется в дополнение к тем, которые описаны ранее в разделе 11. За исключением случаев, когда формируется указатель на член, * доступ должен быть через указатель на, ссылку или объект самого производного класса (или любого класса, полученного из этого класса).

Одна из причин этой проверки доступа к добавлению связана с поведением тех защищенных членов базового класса. Поскольку члены защищены, другой производный класс может добавлять семантику или даже делать оптовые изменения в значении этих полученных членов. (Это одна из причин того, что защищенные данные довольно опасны.) Поскольку ваш класс не обращает внимания на эти дополнения/модификации семантики базового класса, сделанные в других производных классах, лучше всего сделать это, чтобы исключить доступ к элементам базового класса, когда доступ будет осуществляться через базовый класс.

Ответ 3

У вас есть правильная идея, но вы не используете защищенный элемент правильно.

void foo (Base * b) вместо этого должен быть void foo();

и его реализация будет:

void Derived:: foo() { return this- > x; }

Поскольку x является защищенным членом, вы не можете получить к нему доступ из другого объекта - даже если этот объект наследуется от этого класса. Вы можете получить доступ к нему только из самого производного объекта.

Ответ 4

Чтобы дать конкретный пример того, что говорят другие:

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
}

Ответ 5

Что вы по существу сделали, создается экземпляр базы, который имеет другое отношение к производному, чем внутренний экземпляр базы внутри производного. Установка переменной в protected дает унаследованному классу доступ к собственному внутреннему экземпляру базы. Однако создание объекта типа базы в классе является чем-то другим и, следовательно, не разрешает доступ.