Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
###Cpp_лкц1_1.09_11_#дляБАК#29_01_12.doc
Скачиваний:
40
Добавлен:
29.04.2019
Размер:
6.42 Mб
Скачать

Часть II. Объектно-ориентированное программирование

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

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

Операция reinterpret_cast

Операция reinterpret_cast применяется для преобразования не связанных между собой типов, например, указателей в целые или наоборот, а также указателей типа void* в конкретный тип. При этом внутреннее представление данных остается неизменным, а изменяется только точка зрения компилятора на данные.

Формат операции:

reinterpret_cast <тип> (выражение)

Результат операции имеет указанный тип, который может быть ссылкой, указателем, целым или вещественным типом.

Пример:

char *р = reinterpret_cast <char*>(malloc(100)); long 1 = reinterpret_cast <long>(p);

Различие между static_cast и reinterpret_cast позволяет компилятору производить минимальную проверку при использовании static_cast, а программисту — обозначать опасные преобразования с помощью reinterpret_cast. Результат преобразования остается на совести программиста.

Динамическое определение типа

Механизм идентификации типа во время выполнения программы (RTTI) позволяет определять, на какой тип в текущий момент времени ссылается указатель, а также сравнивать типы объектов. Для доступа к RTTI в стандарт языка введена операция typeid и класс typejinfo1.

Формат операции typeid:

typeid (тип) typeid (выражение)

Операция принимает в качестве параметра имя типа или выражение и возвращает ссылку на объект класса typejinfo, содержащий информацию о типе. Если операция не может определить тип операнда, порождается исключение bad_typeid.

1 В старых версиях компиляторов этот класс может называться Typejinfo или typeinfo.

Глава 8. Преобразования типов

239

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

Если операндом является выражение, представляющее собой ссылку на неполиморфный тип, объект type_info содержит информацию о типе выражения, а не о типе объекта, на который оно ссылается.

Операцию typeid можно использовать как с основными, так и с производными типами данных.

Класс type_info описан в заголовочном файле <typeinfo> следующим образом:

class type_info{ public-virtual -typejnfoC):

bool operator==(const type_info& rhs) const; bool operator!=(const type_info& rhs) const; bool before(const type_info& rhs) const; const char* nameO const; private;

type_info(const type_info& rhs); type_info& operator=(const type_info& rhs); }: Метод name возвращает указатель на строку, представляющую имя типа, описываемого объектом типа typejinfo.

Виртуальный деструктор делает класс type_info полиморфным.

Конструктор копирования и операция присваивания объявлены как private, чтобы исключить возможность случайного копирования и присваивания объектов класса.

Операции == и ! = позволяют сравнивать два объекта на равенство и неравенство, а функция before выполняет побуквенное сравнение имен двух типов. Для сравнения используется конструкция вида:

typeid(Tl).before(typeid(T2))

Если имя типа Т1 лексикографически предшествует имени Т2, результат будет истинным.

Точная информация о типе объекта во время выполнения программы может потребоваться, например, когда программист расширяет функциональность некоторого библиотечного базового класса с помощью производного, и невозможно или бессмысленно добавлять к базовому классу виртуальные функции. Например:

#include <typeinfo.h> class B{

public: virtual ~B(){};

}:

class С: public B{

public: virtual void some_method(){ ... };

240