Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
OOP_otvety_k_ekzamenu.doc
Скачиваний:
55
Добавлен:
13.04.2015
Размер:
786.94 Кб
Скачать

29. Понижающее преобразование типа (downcast). Опасности. Поля идентификации типов.

При написании программного кода манипулирующего средствами из базовых классов может возникнуть необходимость в различной обработке объектов в зависимости от их конкретного типа. Предположим, имеется набор транспортных средств, и требуется подсчитать их общий приблизительный вес вместе с перевозимым грузом / пассажирами при максимальной загрузке. Собственный вес является характеристикой любого транспортного средства (имеется метод getWeight в классе Vehicle), однако перевозимый вес оценивается по разным правилам для автобусов и грузовиков. Максимальный вес перевозимого содержимого грузовика известен при его конструировании. А вес пассажиров можно оценить умножением количества пассажирских мест на некоторый условно выбираемый средний вес человека (согласно данным из открытой энциклопедии, средний вес человека на планете оценивается в 62кг).

Имея набор указателей на объекты базового класса не существует простого способа отличить их конкретный тип. Чтобы реализовать описанный алгоритм подсчета суммарного веса в первом варианте введем в базовый класс Vehicle специальное дополнительное идентифицирующее поле перечисляемого типа (m_type), по которому автобусы можно будет отличить от грузовиков не имея указателя на конкретный объект

Производные классы должны скорректировать свои конструкторы, передавая конкретное значение идентифицирующего поля.

При определении веса конкретного транспортного средства следует определить его тип, а затем сделать ПОНИЖАЮЩЕЕпреобразование типа (downcast, движемся вниз по иерархии классов), чтобы извлечь необходимые для подсчета данные из производных классов.

Опасности: Понижающее преобразование типа вниз по иерархии наследования никак не проверяется во время выполнения и, в общем случае, чревато ошибками. При таком преобразовании программист должен быть абсолютно уверен, что объект имеет тот самый тип (либо производный от него), к которому осуществляется такое преобразование.

Это замечание является наиболее серьезным из всех. В принципе, в этом конкретном примере это правило обеспечено логикой конструирования объектов. В общем же случае, если объект реально имеет другой тип, преобразование вниз по иерархии приведет к неправильной интерпретации содержимого памяти. Предположим, происходит преобразование типа вниз к типу Truck, а на самом деле объект относится к типу Bus.

Опасность ситуации состоит в том, что неправильное преобразование довольно трудно обнаружить. Достаточно часто никаких ярких видимых дефектов не проявляется. Обнаружить некорректность преобразования можно намного позже, получив неожиданный результат при дальнейшем вызове методов.

30. Виртуальные функции. Полиморфизм. Цель. Синтаксис, примеры использования.

ВИРТУАЛЬНЫХ ФУНКЦИЙ (virtual functions). Такая особая форма функций,

будучи введенной в базовом классе и помеченной ключевым словом virtual, может быть замещена, или переопределена (overridden), другой реализацией с идентичной сигнатурой в производном классе. А в момент вызова виртуальной функции через указатель или ссылку на базовый класс будет использоваться реализация, соответствующая фактическому типу объекта.

ПОЛИМОРФНЫМ (polymorphism = много форм). Виртуальные функции функционируют таким образом, что при вызове через указатель или ссылку на базовый класс управление попадает в версию функции, соответствующую типу вызываемого объекта, известному в момент его создания. Полиморфизм является одним из трех фундаментальных принципов в объектно-ориентированном программировании,

Отметим преимущества использования такого подхода:

  • основной реализуемый алгоритм не заботится ни о преобразовании типа вниз по иерархии, ни о полноте рассмотрения всех возможных объектов - используется единый интерфейс, предполагая, что объект обеспечит корректное поведение, соответствующее своему классу;

  • при расширении иерархии новыми классами код алгоритма менять не нужно - вместо этого новый класс должен предоставить собственное переопределение виртуальной функции, и тогда он удовлетворит ожидания всех имеющихся использований иерархии.

class Vehicle

{

public:

virtual float getMaxExtraWeight () const { return 0.0f; }

};

Соседние файлы в предмете [НЕСОРТИРОВАННОЕ]