По этой теме стандарт C ++ 03 гласит (выделено мое):
11,5 Доступ защищенного члена
1 Когда друг или функция члена
производный класс ссылается на защищенную нестатическую функцию-член или
Защищенный нестатический элемент данных базового класса, проверка доступа
применяется в дополнение к описанным ранее в пункте
11. За исключением случаев, когда формируется указатель на член (5.3.1), доступ
должен быть через указатель, ссылку или объект производного
сам класс (или любой класс, производный от этого класса) (5.2.5).
Однако то, что вы здесь делаете, пытается получить доступ через указатель на класс base , что недопустимо. Если вы измените подпись на
int func(B* p) // instead of A*
вы обнаружите, что теперь он компилируется нормально.
Это также причина, по которой вы можете без проблем получить доступ к a
изнутри class B
: доступ осуществляется через неявный указатель this
, который имеет тип B*
(снова производный класс). Если вы попробовали это:
A* parent = static_cast<A*>(this);
int x = parent->a; // Does not compile!
Вы обнаружите, что он не скомпилируется по той же причине.
Обратное также применимо: если вы опустите указатель p
на B*
, вы сможете получить доступ к элементу protected
очень хорошо:
class A
{
public:
// Added virtual destructor so that the class acquires a vptr,
// making dynamic_cast possible.
virtual ~A() {};
protected:
int a;
};
class B : public A
{
public:
int func(A* p)
{
// Now if we downcast p to B* we can access a just fine
// Of course if p does not actually point to a B, the
// program will have undefined behavior
int x = dynamic_cast<B*>(p)->a;
}
};