Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
методичка по программированию СУА.doc
Скачиваний:
12
Добавлен:
11.11.2019
Размер:
1.3 Mб
Скачать

Преобразования типов

Определяя класс, программист задает методы и операции, которые применимы к объектам этого класса. Например, при определении класса комплексных чисел была определена операция сложения двух комплексных чисел. При определении класса строк мы определили операцию конкатенации двух строк. Что же происходит, если в выражении мы попытаемся использовать ту же операцию сложения с типами, для которых она явно не задана? Компилятор пытается преобразовать величины, участвующие в выражении, к типам, для которых операция задана. Это преобразование, называемое преобразованием типов, выполняется в два этапа.

Первый этап – попытка воспользоваться стандартными преобразованиями типов, определенными в языке Си++ для встроенных типов. Если это не помогает, тогда компилятор пытается применить преобразования, определенные пользователем. "Помочь" компилятору правильно преобразовать типы величин можно, явно задав преобразования типов.

Явные преобразования типов

Если перед выражением указать имя типа в круглых скобках, то значение выражения будет преобразовано к указанному типу:

double x = (double)1;

void* addr;

Complex* cptr = (Complex*) addr;

Такие преобразования типов использовались в языке Си. Их основным недостатком является полное отсутствие контроля. Явные преобразования типов традиционно использовались в программах на языке Си и, к сожалению, продолжают использоваться в Си++, что приводит и к ошибкам, и к путанице в программах. В большинстве своем ошибок в Си++ можно избежать. Тем не менее, иногда явные преобразования типов необходимы.

Для того чтобы преобразовывать типы, хотя бы с минимальным контролем, можно записать

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

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

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

void* addr;

int* intPtr = static_cast < int* > (addr);

Complex* cPtr = reinterpret_cast <

Complex* > (2000);

Если необходимо ограниченное преобразование типа, которое только преобразует неизменяемый тип к изменяемому (убирает описатель const), можно воспользоваться операцией   const_cast:

const char* addr1;

char* addr2 = const_cast < char* > addr1;

Использование static_cast, const_cast и reinterpret_cast вместо явного преобразования в форме (тип) имеет существенные преимущества. Во-первых, можно всегда применить "минимальное" преобразование, т. е. преобразование, которое меньше всего изменяет тип. Во-вторых, все преобразования можно легко обнаружить в программе. В-третьих, легче распознать намерения программиста, что важно при модификации программы. Сразу можно будет отличить неконтролируемое преобразование от преобразования неизменяемого указателя к изменяемому.