Потребность в ключевом слове public
есть только для классов, определенных с ключевым словом class
, модификатор доступа по умолчанию (для всего - членов данных, функций-членов и базовых классов) равен private
. Так
class World : State {};
совпадает с:
class World : private State {};
и это, вероятно, не то, что вы хотите - это означает, что базовый класс доступен только внутри класса World
. Аутсайдеры "не знают", что наследство там вообще.
Для классов, определенных с ключевым словом struct
, модификатором доступа по умолчанию является public
, поэтому вы могли бы написать:
struct World : State {};
и получите что-то, что выглядит и ведет себя немного как любой другой язык с наследованием. Но ключевое слово struct
и тот факт, что он определяет класс, действительно только для совместимости с C. Вы не найдете много руководств по стилю C ++, которые рекомендуют использовать его только для того, чтобы получить общедоступную доступность по умолчанию - обычно это используется только для классов, которые являются POD, или, возможно, только для классов без функций-членов вообще.
Что касается того, почему C ++ имеет частное наследование в первую очередь: для большинства целей частное наследование является формой композиции. Нормальный состав:
class World {
State state;
public:
void foo() {
state.bar();
state.baz();
and so on
}
};
То есть класс World знает, что он реализован с использованием State, а внешний мир не знает, как реализован World.
против
class World : private State {
public:
void foo() {
bar();
baz();
and so on
}
};
То есть класс World знает, что он реализован, когда является государством, а внешний мир не знает, как он реализован. Но вы можете выборочно раскрыть части интерфейса State, например, поместив using State::bar;
в публичную часть определения World. Эффект такой, как если бы вы кропотливо написали функцию (или несколько перегрузок) в World, каждая из которых делегирует одну и ту же функцию в State.
Однако, кроме того, чтобы избегать ввода, одним из распространенных применений частного наследования является случай, когда класс State
пуст, то есть не имеет элементов данных. Тогда, если он является членом World
, он должен занимать некоторое пространство (по общему признанию, в зависимости от компоновки объекта это может быть пространство, которое в противном случае будет просто заполнением, поэтому это не обязательно увеличивает размер World
), но тогда это базовый класс, тогда появляется вещь, называемая «оптимизация пустого базового класса», и она может быть нулевого размера. Если вы создаете много объектов, это может иметь значение. Частное наследование позволяет оптимизировать, но внешний мир не выведет отношения «есть», потому что не видит наследство.
Это довольно хорошая разница - если сомневаетесь, просто используйте явную композицию. Введение наследования для сохранения типирования очень хорошо, пока оно не приведет к неожиданным последствиям.