Перепутанный на кастинге C++

Я читал много о кастинге C++, и я начинаю запутываться, потому что я всегда использовал кастинг стиля C.

Я считал, что кастинга стиля C нужно избежать в C++ и что reinterpret_cast очень очень опасен и не должен использоваться каждый раз, когда существует альтернатива. Наоборот к не использованию reinterpret_cast, я видел, что оно много раз использовало на MSDN в их примере кода. Это приводит меня задавать свой первый вопрос, когда это в порядке для использования reinterpret_cast?

Например:

LRESULT CALLBACK WndProc(HWND hWnd, UINT Msg, WPARAM wParam, LPARAM lParam)
{
   switch (Msg)
   {
      case WM_CREATE:
      {
          LPCREATESTRUCT lpCreateStruct = reinterpret_cast<LPCREATESTRUCT>(lParam); 
          return 0;
      }
   }

   ...
}

Если бы это не в порядке, то, как я бросил бы значение LPARAM к указателю с помощью только статичный, динамичный, и/или кастинг константы?

Также: Если бы reinterpret_cast не является портативным, как я переписал бы его, чтобы быть портативным (для хорошей практики)

12
задан Marlon 27 February 2010 в 00:48
поделиться

5 ответов

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

Это считается опасным, потому что не выполняет никаких проверок ни во время компиляции, ни во время выполнения. Если вы сделаете ошибку, он может и будет вылетать и ужасно сгорать, и его будет сложно отладить. По сути, вы говорите компилятору: «Я лучше вас знаю, что это на самом деле, поэтому просто скомпилируйте код и позвольте мне позаботиться о последствиях».

8
ответ дан 2 December 2019 в 18:18
поделиться

Причина, по которой вы видите это в MSDN, заключается в том, что Win32 API - это C API, но люди настаивают на приведении примеров в ] C ++ .

Reinterpret cast - это нормально, когда вы пишете код, который взаимодействует с другими библиотеками. Его следует избегать в собственном приложении .

5
ответ дан 2 December 2019 в 18:18
поделиться

Это пример программирования Windows Platform SDK, C API, с помощью C ++. Оконная процедура имеет только параметры WPARAM и LPARAM, и если вам нужно передать указатель на структуру через оконное сообщение, его необходимо преобразовать. На мой взгляд, это вполне приемлемое использование reinterpret_cast <>. Вы не можете избежать приведения, потому что SDK, в который вы пишете, который не является вашим кодом, не был разработан для C ++, что значительно снижает безопасность типов и требует приведения для предоставления общих типов параметров с привязкой C.

Reinterpret_cast <> - это флаг, который сообщает вам, что вам нужно быть осторожным, но его нельзя избегать любой ценой.

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

3
ответ дан 2 December 2019 в 18:18
поделиться

Не неуважительно к MSDN, но MSDN - не лучшее место для правильного кодирования на C ++.

Одна из причин использования reinterpret_cast - это преобразование в / из непрозрачных типов данных. reinterpret_cast не «опасен», просто он легко может облажаться и привести к проблемам в вашем коде, поэтому этого следует избегать.

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

Программисты [неправильно] часто используют приведение типов для «отбрасывания предупреждений компилятора», таких как преобразование из беззнаковых целых чисел в знаковые или из 32-битных целых чисел в 8-битные.

2
ответ дан 2 December 2019 в 18:18
поделиться

По сути, reinterpret_cast "безопасен" со структурами C и базовыми типами (без явных ошибок, таких как приведение int к указателю и обратно, что работает на архитектуре ILP32, но ломается на архитектуре LP64.) В структуре AC нет ничего, кроме возможного заполнения для выравнивания, которое вы не объявили.

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

2
ответ дан 2 December 2019 в 18:18
поделиться
Другие вопросы по тегам:

Похожие вопросы: