Простая проблема наследования в C ++ - PullRequest
5 голосов
/ 12 сентября 2011
#include <iostream>
using namespace std;
class A
{
protected:
    int a;
};
class B : public A
{
public:
    int func(A* p)
    {
        cout << p->a;
    }
};

Я действительно не могу понять, почему я не могу получить доступ к 'a' через 'p-> a'.

Есть ли в любом случае доступ к члену p «a» в классе B, не меняя «protected» на «public»?

Ответы [ 3 ]

10 голосов
/ 12 сентября 2011

По этой теме стандарт 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;
    }
};
2 голосов
/ 12 сентября 2011

Использование p->a только позволит вам получить доступ к общедоступным переменным A. Поскольку a является защищенной переменной, вы должны использовать cout << a, так как a являетсяунаследовано в классе B.

Я думаю, вы могли бы использовать cout << p->a для friend класса B.

Или используя указатель на B вместо указателя на A* * * * * * * * * * * * * * * *.

1 голос
/ 12 сентября 2011

Ааа, это хороший вопрос.Во-первых, позвольте мне начать с того, что B НЕ является другом A и поэтому не имеет доступа к частным лицам (или защищенным) A через представление объекта "A".Несмотря на то, что мы находимся в области действия класса B, мы не можем просто ходить и смотреть на рядовые данные A (или защищенные).

ОДНАКО, B имеет a.И он имеет к нему доступ, потому что он объявлен защищенным членом A.Но единственный способ увидеть int a внутри B - это получить его из вида B объекта.

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