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

Преобразования указателей и ссылок

При работе с указателями и ссылками компилятор автоматически выполняет только два вида преобразований.

Если имеется указатель или ссылка на производный тип, а требуется, соответственно, указатель или ссылка на базовый тип.

Если имеется указатель или ссылка на изменяемый объект, а требуется указатель или ссылка на неизменяемый объект того же типа.

size_t strlen(const char* s);

// прототип функции

class A { };

class B : public A { };

char* cp;

strlen(cp);

// автоматическое преобразование из

// char* в const char*

B* bObj = new B;

// преобразование из указателя на производный класс

A* aObj = bObj;

// к указателю на базовый класс

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

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

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

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 вместо явного преобразования в форме (тип) имеет существенные преимущества. Во-первых, можно всегда применить "минимальное" преобразование, т. е. преобразование, которое меньше всего изменяет тип. Во-вторых, все преобразования можно легко обнаружить в программе. В-третьих, легче распознать намерения программиста, что важно при модификации программы. Сразу можно будет отличить неконтролируемое преобразование от преобразования неизменяемого указателя к изменяемому.

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