технические аспекты 'isa' в c ++ - PullRequest
1 голос
/ 03 октября 2010

что именно это означает из technical point of view, я понял, что это означает, что мои derived class всегда можно преобразовать в base class, вот и все?Я читаю некоторые материалы без каких-либо ссылок на технические аспекты, только философия!заранее спасибо

Ответы [ 2 ]

4 голосов
/ 03 октября 2010

это означает, что мой производный класс всегда можно преобразовать в базовый класс

На самом деле это значит лучше, чем это. int всегда можно преобразовать в float, но это не означает, что int "является" float. Это просто означает, что float может быть построен из int. Точно так же у вас могут быть пользовательские классы, которые конвертируются, но не имеют других отношений.

При наследовании указатель или ссылка на производный класс всегда могут быть преобразованы в указатель или ссылку на базовый класс [*]. То есть объект производного класса может стоять вместо объекта базового класса. Это на самом деле одна из тех вещей. Если человек может заменить хирурга мозга, значит, он хирург.

Одним формальным определением, если "является", является принцип подстановки Барбары Лисков . По общему признанию, это все еще философия, но это очень здравая философия, и она напрямую связана с тем, как вы пишете программы.

Еще одна вещь, которую вы должны учитывать при использовании наследования в C ++, это разница между полиморфизмом во время выполнения (достигается с помощью функций virtual) и статическим полиморфизмом (который на самом деле вообще не требует наследования). При вызовах не виртуальных функций версия вызываемой функции всегда является версией, определенной в классе, который, как сообщается компилятору, имеет объект (статический тип). Это может на самом деле работать неправильно, если оно перегружено в производном классе. При виртуальных вызовах вызываемая версия - это версия, определенная в классе, которым на самом деле является объект (динамический тип). Важно решить, к какому из двух видов «вы» вы стремитесь.

[*] и объект должен быть правильно доступен через указатель, то есть. Вы всегда можете принудительно указать типы указателей с помощью reinterpret_cast, но я здесь не это имею в виду. И есть некоторые поразительные детали - если базовый класс неоднозначен, вы не можете конвертировать указатель за один раз, но вы можете сделать это явно, используя несколько однозначных приведений. Если базовый класс недоступен, то вы можете преобразовать его, но только с приведением в стиле C, а не неявным образом. Приведение в стиле C действует как static_cast, который игнорирует доступность, а не как reinterpret_class. Таким образом, вы получаете рабочий указатель, но, надеюсь, также сильное чувство, что вы делаете что-то очень неправильное; -)

2 голосов
/ 03 октября 2010

Производный класс может быть преобразован только в доступный и однозначный базовый класс в заданной точке R. Нет недостатка в ссылках и в каком другом месте, кроме самого стандарта C ++.

$ 10,2хорошая справка: производный класс сам может служить базовым классом, подлежащим контролю доступа;см. 11.2.Указатель на производный класс может быть неявно преобразован в указатель на доступный однозначный базовый класс (4.10).Значение типа производного класса может быть связано со ссылкой на доступный однозначный базовый класс (8.5.3).- конец примечания]

И снова

$ 10.3 - "Список базовых спецификаторов определяет тип подобъектов базового класса, содержащихся в объекте типа производного класса. [..] Здесь объект класса Derived2 будет иметь подобъект класса Derived, который, в свою очередь, будет иметь подобъект класса Base. [...]

С точки зрения принципов OOAD:

Я бы лично порекомендовал статьи Роберта Мартина , чтобы хорошо овладеть этим, особенно принципом OCP. Я не могу побить ясность и авторитет, которыми автор объясняет эти легендарныеРекомендации OOAD

Также посмотрите на LSP, как объяснено в посте @Steves

...