Явное приведение static_cast в С++, начало знакомства

В С++ можно явно приводить типы с помощью нескольких кастов. В зависимости от вида преобразования, выбирают одно из четырёх. Часто для работы с самыми обычными типами выбирают операцию static_cast.
Для того, чтобы вообще понимать страшно выглядящий, но очень несложный, синтакисис её применения:



Желательно ознакомиться с темой:

Моя непосредственно текущая статья не полностью раскрывает тему static_cast, а только даёт волшебный пинок к пониманию. Поэтому, после ознакомления с общим принципом, Вам потребуется поизучать информацию в разных источниках (лучше почитать книги авторитетных авторов).
Я не могу сейчас раскрыть тему полностью, потому что в настоящий момент, путь "самурая", рискнувшего изучать язык С++, следующего порядку тем моего сайта, ограничивается препятствиями из самых обычных функций. Мы ещё не дошли до классов. А при работе с классами и применением наследования, у static_cast есть ещё некоторые правила. По этой причине я только очень поверхностно знакомлю читателя с описываемым в статье способе преобразований типов. Имейте это в виду.
В С++ иногда срабатывают неявные преобразования типов. Как правило, они доставляют проблем приходящим в С++ новичкам. Поверхностное ознакомление с неявными преобразованиями описывалось в статье С++ Неявные преобразования численных типов. Но ещё бывает нужда в ручном преобразовании неподходящего типа к нужному. На самом деле, чем больше Вы стараетесь избежать явных привидений типов, тем лучше. В идеале не использовать ручное приведение типов вообще. Но тем не менее, Вы неоднократно ещё будете преобразовывать типы.
В С++ возможно использовать явное приведение в стиле языка С и в стиле языка С++. В стиле языка С++ есть такие вот варианты:

  • dynamic_cast
  • static_cast (этот сейчас описывается)
  • const_cast
  • reinterpret_cast
Создатель языка С++: Бьярне Страуструппе — считал, что приведения в стиле языка С и в функциональном стиле обладают ужасным свойством: позволяют не вникать в то, что именно они делают. Поэтому в С++ была добавлена возможность явных приведений с помощью операций, перечисленных выше. Эти операции ограничены в своих возможностях, а их непонятные (поначалу) названия хорошо отображают цель использования преобразования и помогают избежать некоторых ошибок ещё на стадии написания кода.
Так как эта статья ограничена static_cast, то дальше будет написано только про static_cast и, как было сказано ранее, только частично.
Схема приведения static_cast выглядит так:

Демонстрация желания преобразования типов
<
Тип, к которому преобразовываем
>
(
Значение, из которого выделяем тип
)
;
Комментарий

static_cast
<
int
>
(
155.55
)
;
Преобразование: из double в int

static_cast
<
double
>
(
value1
)
;
Преобразование: из выделенного из value1 типа в double

static_cast
<
MyType
>
(
value2
)
;
Преобразование: из выделенного из value2 типа в MyType

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

Такое приведение считается экстримальным и использовать его очень не рекомендуется. Опасно. Этому стоит предпочитать те страшные касты, которые введены в С++ и жутко выглядят (static_cast, const_cast, dynamic_cast…).
Вернёмся к static_cast. И посмотрим, почему он лучше более простого по написанию варианта:

Введённые в С++ касты (приёмы преобразований типов) не дают программе собраться, если преобразование черезчур опасное. Эти ограничения повышают надёжность готовых продуктов.

В показанном примере происходит попытка приведения типа int, отдаваемого функцией foo_int к типу void*. В случае с С-style приведением ошибок никаких нет и программа успешно запустится, но в ходе её работы могут возникнуть проблемы.

Поговорим немного о более сложных для новичков вещах. Cогласно документации языка С++, операция static_cast позволяет явно преобразовать указатели связанных типов один в другой. Если программист использует static_cast для приведения встроенных в С++ примитивных типов, то операцией static_cast используются правила приведения встроенных типов. Если приведение не допускается, то static_cast не даст скомпилироваться программе, что и было продемонстрировано выше: приведение целочисленного типа к указателю на этапе компиляции не удалось. Для собственного удобства первое время можете считать, что если не можете присвоить в одну переменную значение какого-то выражения, то и static_cast не станет приводить тип того выражения к типу той переменной.

Причины некомпилирования достаточно просты. Нельзя привести тип, который по сути есть строка, к типу число. У этих типов разное внутренне представление. Хотя приведение в стиле С плюёт на внутренние представления типов и игнорирует сам факт собственного неумения выводить число из строки в неявном виде. static_cast более умный, скомпилироваться программе не даёт. Вы если не поняли, то смотрите, в чём опасность:


Хоть программа и собралась, результат работы плачевен. А static_cast просто бы не дал компилятору собрать программу, предупредив возникновение нехорошей ошибки. Он молодец.

Язык С++ позволяет создавать свои собственные типы данных.

  • В случае с типами, определёнными программистом, используются правила приведения, описанные программистом.

В примерах статьи я применял указатель на void

  • К типу void можно привести любой тип.


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

Я полагаю, что для поверхностного ознакомления этой информации должно хватить и что вы сможете теперь без труда и применять этот каст, и понимать, зачем другие пишут именно так. Дальнейшее знакомство всё глубже и глубже окунает в изучение классов.
  • Если нужно выполнять приведение каких-то простых типов, встроенных в С++, то приведение с помощью static_cast оправдано.
Но не надо себе воображать, что использование static_cast вообще хорошо. Любое собственноручное приведение типов черевато последствиями. Нужно максимально избегать необходимости приведения типов в серьёзных программах.
Советую отложить где-то закладку, что информация о static_cast была получена не в полном объёме, что после изучения полиморфизма, нужно вернуться к этому способу приведения типов.
Некоторые полезные сведения о static_cast:

  • Операция static_cast не может удалять атрибуты const, volatile.
  • Операция static_cast выполнятся во время компиляции программы.
  • Операция static_cast использует встроенные правила приведения для встроенных типов и программистские правила приведения в программистских типах.
  • Обычно static_cast используется, когда требуется преобразовать числовые типы данных.
А ещё нужно знать немного о приоритете операций и понимать, что эти приоритеты не отменял никто:

В первом случае сначала вычисляется выражение в круглых скобках, а потом происходит преобразование полученного в результате вычисления типа к типу double
Во втором случае сначала тип, выводимый из числа 5, т. е. int приводится к типу double, после чего целое double делится на 2, т. е. на int. Результат double.
На заметку:

  • В некоторых случаях static_cast используют для обхода предупреждений о приведениях с потерей точности.

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *

Поиск

 
     

Случайная книга в электронном формате

https://www.litres.ru/uriy-schupak/win32-api-razrabotka-prilozheniy-dlya-windows/?lfrom=15589587
Яндекс.Метрика