Доступ к защищенным членам в производном классе
Вчера я столкнулся с ошибкой и, хотя мне было легко обойти, я хотел убедиться, что я правильно понимаю С++.
У меня есть базовый класс с защищенным членом:
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
. Я, однако, что, когда вы используете публичное наследование, защищенные переменные все еще видны производному классу.
Ответы
Ответ 1
Вы можете получить доступ только к защищенным членам в экземплярах вашего типа (или получить их из вашего типа).
Вы не можете получить доступ к защищенным членам экземпляра родительского или двоюродного типа.
В вашем случае класс Derived
может получить доступ только к элементу b
экземпляра Derived
, а не к другому экземпляру Base
.
Изменение конструктора для получения экземпляра Derived
также решит проблему.
Ответ 2
У вас есть доступ к защищенным членам Derived
, но не к Base
(даже если это единственная причина, по которой он защищен членом Derived
, потому что он унаследован от Base
)
Ответ 3
Как уже упоминалось, это так, как работает язык.
Другим решением является использование наследования и переход к родительскому методу:
class Derived : public Base
{
protected:
int d;
public:
void DoSomething(const Base& that)
{
Base::DoSomething(that);
d=0;
}
};
Ответ 4
Доступ к элементам protected
:
- через
this
указатель
- или защищенным членам того же типа, даже если они объявлены в базе
- или из классов друзей, функций
Для решения вашего дела вы можете использовать один из двух последних вариантов.
Принять Производные в Производных:: 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;
}
};
В некоторых случаях вы также можете рассматривать публичные геттеры.
Ответ 5
class Derived : public Base
{
protected:
int d;
public:
void DoSomething()
{
b+=this->b;
d=0;
}
};
//this will work
Ответ 6
Вы можете попробовать с static_cast <const Derived *> (pBase) → 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)->b;
d=0;
}
};
Ответ 7
Используйте указатель this
для доступа к защищенным членам
class Derived : public Base
{
protected:
int d;
public:
void DoSomething(const Base& that)
{
this->b+=that.b;
d=0;
}
};