ошибка: void Base :: output () 'защищен в этом контексте - PullRequest
3 голосов
/ 07 апреля 2010

Я запутался в ошибках, вызванных следующим кодом .В Derived :: doStuff я могу получить доступ к Base :: output напрямую, вызвав его.

Почему я не могу создать указатель на output() в том же контексте, в котором я могу вызвать output()?

(я думал, что защищенный / приватный определяет, можете ли вы использовать имя в определенном контексте, но, по-видимому, оно неполно?)решение?

#include <iostream>
using std::cout; using std::endl;

template <typename T, typename U>
void callback(T obj, U func)
{
  ((obj)->*(func))();
}

class Base
{
protected:
  void output() { cout << "Base::output" << endl; }
};

class Derived : public Base
{
public:
  void doStuff()
  {
// call it directly:
    output();
    Base::output();

// create a pointer to it:
//    void (Base::*basePointer)() = &Base::output;
// error: 'void Base::output()' is protected within this context
    void (Derived::*derivedPointer)() = &Derived::output;

// call a function passing the pointer:
//    callback(this, &Base::output);
// error: 'void Base::output()' is protected within this context
    callback(this, &Derived::output);
  }
};

int main()
{
  Derived d;
  d.doStuff();
}

Редактировать: Я хотел бы знать, где это находится в stardard, но в основном я просто пытаюсь обернуть голову вокруг концепции.Я думаю, что моя проблема в том, что callback не имеет доступа к защищенным членам Derived, но он может вызвать Derived::output, если вы передадите ему указатель.Чем защищенный элемент Derived из Derived отличается от защищенного элемента Derived из Base?

Ответы [ 2 ]

2 голосов
/ 07 апреля 2010

Короче говоря, это "потому что так говорится в стандарте". Зачем? Я не знаю, я написал пару парней по стандартам, но пока не получил ответа.

В частности, 11.5.1 (из C ++ 0x FCD ):

Дополнительная проверка доступа за пределами те, что описаны ранее в пункте 11 применяется, когда нестатические данные член или нестатическая функция-член является защищенным членом своего имени класс (11.2) 114 Как описано ранее, Доступ к защищенному члену предоставлен, потому что ссылка происходит у друга или члена какого-то класса C. Если доступ заключается в формировании указателя на член (5.3.1), спецификатор вложенного имени должен обозначать C или класс, производный от C. Все остальные доступ включает (возможно, неявный) выражение объекта (5.2.5). В этом случай, класс объекта выражение должно быть C или класс полученный из C.

Edit:

Кроме того, вы увидите, что измените код на следующий, в соответствии с тем, что указано в стандарте, он будет скомпилирован (и запущен) без ошибок:

void (Base::*derivedPointer)() = &Derived::output;
1 голос
/ 07 апреля 2010

Редактировать: я не уверен, если это "Где это в стандарте?" вопрос или "Почему это так спроектировано?" вопрос, это отвечает на последний вопрос (у меня нет копии самого стандарта для игры)

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

В этом примере callback не имеет доступа к base и поэтому не может вызывать одну из его частных функций.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...