Делая наследование частным, вы в основном говорите, что даже тот факт, что B наследует от A (вообще), является частным - не доступен / не виден внешнему миру.
Без проникновения вдолгое обсуждение того, что произойдет, если это будет разрешено, простой факт заключается в том, что это не разрешено.Если вы хотите использовать указатель на базу для ссылки на объект производного типа, то вы в значительной степени застряли с использованием публичного наследования.
Частное наследование не обязательно (или дажеобычно), чтобы следовать принципу замены Лискова .Публичное наследование утверждает, что производный объект может быть заменен объектом базового класса, и правильная семантика будет все еще результатом.Тем не менее, личное наследование не подтверждает это.Обычное описание отношений, подразумеваемых частным наследованием, «реализовано в терминах».
Открытое наследование означает, что производный класс поддерживает все возможности базового класса и потенциально добавляет еще больше.Частное наследование часто означает более или менее противоположное: что производный класс использует общий базовый класс для реализации чего-либо с более ограниченным интерфейсом.
Например, давайте на минуту предположим, что контейнеры в стандарте C ++библиотека была реализована с использованием наследования, а не шаблонов.В текущей системе std::deque
и std::vector
являются контейнерами, а std::stack
является адаптером контейнеров, который обеспечивает более ограниченный интерфейс.Так как он основан на шаблонах, вы можете использовать std::stack
в качестве адаптера для std::deque
или std::vector
.
Если бы мы хотели предоставить по существу то же самое с наследованием, мы бы, вероятно, использовали частное наследованиепоэтому std::stack
будет выглядеть примерно так:
class stack : private vector {
// ...
};
В этом случае мы определенно не хотим, чтобы пользователь мог манипулировать нашим stack
, как если бы это был vector
.Это может (и, вероятно, может) нарушить ожидания стека (например, пользователь может вставлять / удалять элементы посередине, а не просто как в стеке, как предполагалось).В основном мы используем vector
в качестве удобного способа реализации нашего стека, но если (например) мы изменили реализацию для stack
в автономном режиме (без зависимости от базового класса) или повторно реализовали ее с точки зренияstd::deque
, мы не хотим, чтобы это влияло на любой клиентский код - для клиентского кода это должен быть просто стек, а не какой-то специализированный набор векторов (или deque).