Есть ли какие-либо примеры, когда нам * нужно * защищенное наследование в C ++?
-
09-06-2019 - |
Вопрос
Хотя я видел редкие случаи, когда Частное было необходимо наследование, я никогда не сталкивался со случаем, когда защищенный необходимо наследование.У кого-нибудь есть пример?
Решение
Люди здесь, похоже, путают защищенное наследование классов и защищенные методы.
Черт возьми, я никогда не видел, чтобы кто-нибудь использовал защищенное наследование классов, и, если я правильно помню, я думаю, Страуструп даже считал "защищенный" уровень ошибкой в c ++.Вы мало что сможете сделать, если уберете этот уровень защиты и будете полагаться только на общедоступные и частные данные.
Другие советы
Существует очень редкий случай использования защищенного наследования.Это то место, где вы хотите использовать ковариация:
struct base {
virtual ~base() {}
virtual base & getBase() = 0;
};
struct d1 : private /* protected */ base {
virtual base & getBase() {
return this;
}
};
struct d2 : private /* protected */ d1 {
virtual d1 & getBase () {
return this;
}
};
Предыдущий фрагмент пытался скрыть свой базовый класс и обеспечить контролируемую видимость баз и их функций, по какой-либо причине, путем предоставления функции "GetBase".
Однако это приведет к сбою в struct d2
, поскольку d2
не знает , что d1
является производным от base
.Таким образом, covariance
не сработает.Выходом из этого является получение их защищенными, чтобы наследование было видно в d2.
Аналогичный пример использования этого - когда вы производите из std::ostream
, но не хотите, чтобы случайные люди писали в ваш поток.Вы можете предоставить виртуальную getStream
функция, которая возвращает std::ostream&
.Эта функция могла бы выполнить некоторую подготовку потока к следующей операции.Например, ввод определенных манипуляторов.
std::ostream& d2::getStream() {
this->width(10);
return *this;
}
logger.getStream() << "we are padded";
C ++ FAQ Lite упоминания о случае, когда использование частного наследования является законным решением (см. [24.3.] Что мне следует предпочесть:композиция или частное наследование?).Это когда вы хотите вызвать производный класс изнутри частного базового класса через виртуальную функцию (в данном случае derivedFunction()
):
class SomeImplementationClass
{
protected:
void service() {
derivedFunction();
}
virtual void derivedFunction() = 0;
// virtual destructor etc
};
class Derived : private SomeImplementationClass
{
void someFunction() {
service();
}
virtual void derivedFunction() {
// ...
}
// ...
};
Теперь, если вы хотите получить производное от производного класса, и вы хотите использовать Base::service()
изнутри производного класса (допустим, вы хотите переместить Derived::someFunction()
к производному классу), самый простой способ добиться этого - изменить частное наследование Base
к защищенному наследству.
Извините, не могу привести более конкретный пример.Лично мне нравится делать все наследование общедоступным, чтобы не тратить время на обсуждения "должен ли я сделать отношения наследования защищенными или приватными".