это означает, что мой производный класс всегда можно преобразовать в базовый класс
На самом деле это значит лучше, чем это. int
всегда можно преобразовать в float
, но это не означает, что int "является" float. Это просто означает, что float может быть построен из int. Точно так же у вас могут быть пользовательские классы, которые конвертируются, но не имеют других отношений.
При наследовании указатель или ссылка на производный класс всегда могут быть преобразованы в указатель или ссылку на базовый класс [*]. То есть объект производного класса может стоять вместо объекта базового класса. Это на самом деле одна из тех вещей. Если человек может заменить хирурга мозга, значит, он хирург.
Одним формальным определением, если "является", является принцип подстановки Барбары Лисков . По общему признанию, это все еще философия, но это очень здравая философия, и она напрямую связана с тем, как вы пишете программы.
Еще одна вещь, которую вы должны учитывать при использовании наследования в C ++, это разница между полиморфизмом во время выполнения (достигается с помощью функций virtual
) и статическим полиморфизмом (который на самом деле вообще не требует наследования). При вызовах не виртуальных функций версия вызываемой функции всегда является версией, определенной в классе, который, как сообщается компилятору, имеет объект (статический тип). Это может на самом деле работать неправильно, если оно перегружено в производном классе. При виртуальных вызовах вызываемая версия - это версия, определенная в классе, которым на самом деле является объект (динамический тип). Важно решить, к какому из двух видов «вы» вы стремитесь.
[*] и объект должен быть правильно доступен через указатель, то есть. Вы всегда можете принудительно указать типы указателей с помощью reinterpret_cast
, но я здесь не это имею в виду. И есть некоторые поразительные детали - если базовый класс неоднозначен, вы не можете конвертировать указатель за один раз, но вы можете сделать это явно, используя несколько однозначных приведений. Если базовый класс недоступен, то вы можете преобразовать его, но только с приведением в стиле C, а не неявным образом. Приведение в стиле C действует как static_cast
, который игнорирует доступность, а не как reinterpret_class
. Таким образом, вы получаете рабочий указатель, но, надеюсь, также сильное чувство, что вы делаете что-то очень неправильное; -)