Применение оператора dynamic_cast для указателей и ссылок. Основные цели использования. Отличия от операторов static_cast, reinterpret_cast и const_cast

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

Реализация оператора dynamic_cast выполняет приблизительно следующие действия:

-извлекает структуру std::type_info из преобразуемого указателя полиморфным способом;

-извлекает структуру std::type_info статическим способом по типу целевого указателя;

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

Для указателей

void f ( Base & _base )

{

if ( Derived* pDerived = dynamic_cast< Derived * >( & _base ) )

do1();

else

do2();

}

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

Оператор dynamic_cast можно применять не только к указателям, но и к ссылкам:

void f ( Base & _base )

{

Derived & derived = dynamic_cast< Derived & >( _base );

...

}

Такое преобразование для ссылок, по сути, является не вопросом к объекту как с указателями, а утверждением. Утверждение проверяется во время выполнения. В случае успеха преобразования, возвращается ссылка на объект с соответствующей коррекцией адреса начала объекта. Однако, поскольку ссылка не может быть неинициализированной, оператор dynamic_cast не может вернуть значение nullptr в случае неудачи, и реакцией в таком случае является генерация исключительной ситуации.

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

● преобразование указателя или ссылки на базовый класс вниз по иерархии с гарантированной проверкой во время выполнения;

● осуществление преобразования типа без наличия полного определения всей иерархии участвующих классов в точке приведения (часть иерархии объявлена только форвардно);

● приведение от указателя или ссылки на виртуальный базовый класс к производному классу (принципиально невозможно во время компиляции).

· Оператор reinterpret_cast. Применяя такое преобразование программист сообщает компилятору о явном намерении интерпретировать содержимое памяти существующего объекта принципиально другим способом. Само преобразование осуществляется во время компиляции.

· Ни один из трех описанных операторов преобразования не может преобразовать указатель на константный объект в указатель на объект с правом на запись. Для таких целей используется специальный оператор const_cast. Оператор const_cast также можно использовать для “снятия” модификатора volatile

Наши рекомендации