困惑于C ++铸造

时间:2010-02-27 00:48:39

标签: c++ casting

我一直在阅读很多关于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;
      }
   }

   ...
}

如果不行,那么如何仅使用静态,动态和/或const转换将LPARAM值转换为指针?

另外:如果reinterpret_cast不可移植,我如何将其重写为便携式(为了良好实践)

5 个答案:

答案 0 :(得分:8)

如果您知道指针最初是目标类型,则可以使用reinterpret_cast。任何其他用途都利用了依赖于实现的行为,尽管在许多情况下这是必要且有用的,例如将指向结构的指针转换为指向字节的指针,以便可以序列化。

它被认为是危险的,因为它不会在编译时或运行时进行检查。如果你犯了一个错误,它会崩溃并烧毁,并且难以调试。你基本上是在告诉编译器“我比你知道的更好,所以只需编译代码,让我担心后果。”

答案 1 :(得分:5)

您在MSDN上看到它的原因是因为Win32 API是 C API,但人们坚持在 C ++ 中提供示例。

当您编写与其他库接口的代码时,重新解释强制转换是正常的。应该避免在您自己的应用中。

答案 2 :(得分:3)

这是使用C ++编写Windows Platform SDK(C API)的示例。窗口过程只有WPARAM和LPARAM参数,如果需要通过窗口消息将指针传递给结构,则必须进行转换。这是reinterpret_cast&lt;&gt;的完全可接受的用法。在我看来。您无法避免转换,因为您编写的SDK(不是您的代码)不是为C ++设计的,更不用说类型安全性,并且需要转换来提供带有C绑定的通用参数类型。

reinterpret_cast&lt;&gt;这是一个标志,让你知道你需要小心,但不能不惜一切代价避免。

另一方面,如果您控制代码,API和消费者的两面,最好制作一个类型安全的API,并且不要求消费者执行强制转换以正确使用它

答案 3 :(得分:2)

不要不尊重MSDN,但MSDN不是正确进行C ++编码的最佳位置。

使用reinterpret_cast的一个原因是当您向/从opaque数据类型转换时。 reinterpret_cast不是“危险的”,只是它很容易搞砸并导致代码出现问题,这就是应该避免的原因。

首选C ++样式转换的原因是,static_cast是类型安全的,并且所有转换时间都更容易搜索。

程序员[错误地]经常使用强制转换来“抛弃编译器警告”,例如从无符号整数转换为有符号整数,或从32位整数转换为8位整数。

答案 4 :(得分:2)

基本上reinterpret_cast对于C结构和基本类型是“安全的”(将int转换为指针和背面等明显的错误,这可以在ILP32体系结构上运行,但在LP64体系结构上会中断。)AC结构没有任何内容,除了可能的对齐填充,你没有声明。

reinterpret_cast对C ++多态类型不安全,因为编译器会将数据项插入到您的类中 - 例如 指向虚拟表的指针 指向虚拟基类的指针 。其他C ++强制转换用于调整这些,例如,从指针到基类的向下转换为指向派生类的指针,reinterpret_cast和C风格的强制转换不会。