Приведениетипов. Операторыstatic_cast, reinterpret_cast, dynamic_cast.



Приведе́ниети́па (typeconversion) — преобразование значения переменной одного типа в значение другого типа. Выделяют явное и неявное приведения типов.

· При явном приведении указывается тип переменной, к которому необходимо преобразовать исходную переменную.

· При неявном приведении преобразование происходит автоматически, по правилам, заложенным в данном языке программирования.

· Также в языке могут быть заданы специальные функции для приведения.

Неявное приведение

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

В языке C:

double d; // вещественный тип

long l; // целый тип

int i; // целый тип

if (d >i) d = i;

if (i> l) l = i;

if (d == l) d *= 2;

Каждый раз при выполнени операции сравнения или присваивания переменные разных типов будут приведены к единому типу. Следует с осторожностью использовать неявное приведение типа. При переводе числа из вещественного типа в целочисленный, дробная часть отсекается. Обратное приведение из целочисленного типа к вещественному также может привести к понижению точности, что связано с различным представлением вещественных и целочисленных чисел на машинном уровне. К примеру, вещественный тип single стандарта IEEE 754 не может точно представить число 16777217, в то время как 32-битный целочисленный тип может. Это может привести к ситуациям, когда сравнение на равенство одного и того же числа, представленного типами (int и single) будет выдавать ложный результат (числа не равны друг другу).

Явное приведение типа

В языке C++ существует четыре разновидности приведения типа. Все четыре типа записываются в виде

xxx_cast<type_to>(expression_from)

Например:

y = static_cast<signed short>(65534); // будетприсвоено -2

Громоздкие ключевые слова являются напоминанием программисту, что приведение типа чревато проблемами.

static_cast

Назначение: Приведение типа по обычным правилам, когда компилятор отказывается привести его автоматически (отличается от применяемого в Си (type_to)expression_from только тем, что с указателями на произвольные типа не работает, может применяться только для преобразования void * к другому указателю и для преобразования вниз по иерархии классов; для произвольных указателей применяется reinterpret_cast). Применяется:

· для вычислений в более широком числовом типе (например, для дробных вычислений с целыми числами);

· чтобы избавиться от предупреждения «Возможная потеря точности» при переводе в более узкий числовой тип;

· для указателей и ссылок при конвертации в родительский тип;

· для типов с конструкторами или операциями конвертации наподобие operatortype_to;

· в шаблонах — компилятор уже при специализации шаблона решает, какие операции использовать;

· в операции?:, у которой then- и else-части должны иметь один тип.

· Ограничения на expression_from: нет.

· Ограничения на type_to: должен найтись способ преобразования в type_to.

· Производит ли код: в общем случае да.

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

// Возвращаетпроцентпопаданий.

doublehitpercent(constintaHitCount, constintaShotCount)

{

if (aShotCount==0) return 0.0;

// Нам нужно дробное деление, а не целочисленное - поэтому переведём делимое и делитель в double

returnstatic_cast<double>(aHitCount*100) / static_cast<double>(aShotCount);

}

string s = static_cast<string>("Hello!"); // аналогично string s = string("Hello!");

string s = (string)"Hello!"; // синтаксисСитожеработает

string s = static_cast<string>(5); // не компилируется - нет подходящего конструктора

dynamic_cast

· Назначение: Проводит преобразование типа, предварительно убедившись (с помощью RTTI), что объект expression_from в действительности является объектом типа type_to. Если нет: для указателей возвращает NULL, для ссылок устанавливает аварийную ситуацию std::bad_cast.

· Ограничения на expression_from: выражение должно быть ссылкой или указателем на объект с хотя бы одной виртуальной функцией.

· Ограничения на type_to: ссылка или указатель на дочерний по отношению к expression_from тип.

· Производит ли код: да.

· Возможные ошибки: относительно безопасно. Логические ошибки возможны, если подать аргумент, не имеющий тип type_to, в то время как код не приспособлен к этому.

reinterpret_cast

· Назначение: Участок памяти рассматривается как объект другого типа.

· Ограничения на expression_from: порядковый тип (логический, символьный, целый, перечисляемый), указатель, ссылка.

· Ограничения на type_to: для порядкового типа или указателя — порядковый тип или указатель. Для ссылки — ссылка.

· Производит ли код: нет.

· Возможные ошибки: Участок в реальности может и не иметь этого типа. Нет никакой возможности проверить это, всю ответственность за корректность преобразования программист берёт на себя.

// Возвращает true, если число конечное, и false - если бесконечное или NaN.

boolisfinite(const double x)

{

const uint64_t &y = reinterpret_cast<const uint64_t&>(x);

return ((y & UINT64_C(0x7FF0000000000000))!= UINT64_C(0x7FF0000000000000));

}

// Ошибка - выражение x+5.0 не является ссылкой.

const long long& y = reinterpret_cast<const long long&>(x+5.0);


Дата добавления: 2015-12-21; просмотров: 1; Мы поможем в написании вашей работы!

Поделиться с друзьями:






Мы поможем в написании ваших работ!