C++ 当静态_cast和重新解释_cast具有相同效果时,使用哪一个?

C++ 当静态_cast和重新解释_cast具有相同效果时,使用哪一个?,c++,winapi,casting,C++,Winapi,Casting,可能重复: 通常,特别是在Win32编程中,需要从一种不透明类型转换到另一种不透明类型。例如: HFONT font = cast_here<HFONT>( ::GetStockObject( SYSTEM_FONT ) ); HFONT font=cast_此处(::GetStockObject(SYSTEM_font)); static_cast和reinterpret_cast在这里都适用,并且具有完全相同的效果,因为HFONT是指向专门用于定义HFONT的伪结构的指针

可能重复:

通常,特别是在Win32编程中,需要从一种不透明类型转换到另一种不透明类型。例如:

 HFONT font = cast_here<HFONT>( ::GetStockObject( SYSTEM_FONT ) );
HFONT font=cast_此处(::GetStockObject(SYSTEM_font));
static_cast和reinterpret_cast在这里都适用,并且具有完全相同的效果,因为HFONT是指向专门用于定义HFONT的伪结构的指针,而GetStockObject()返回的HGDIOBJ是void*指针


哪一个-静态转换或重新解释转换-更可取?

静态转换总是更可取,除非绝对必要,否则避免执行
重新解释转换

reinterpret\u cast
是最不安全的类型转换


有关何时应使用哪种类型转换的更多信息。

首选静态类型转换

<> P>从Scott Meyers

中获得更有效的C++ 此运算符[reinterpret_cast]用于执行类型转换 其结果几乎为零的转换 始终定义实现。作为一个 结果,很少重新解释铸型 便携式

reinterpret_cast最常见的用法是在函数指针类型之间进行转换


因为reinterpret_cast是由实现定义的,所以我的经验法则是:“在我可以的地方进行静态的reinterpret_cast,在我必须的地方进行reinterpret_cast”


(撇开其他因素不谈)

我认为静态因素更可取。这里还有更多关于这方面的讨论。

说演员阵容将产生同样的影响是不正确的。演员扮演两个完全不同的角色:

  • static\u cast(x)
    表示将表达式
    x
    转换为类型
    T
  • reinterpret\u cast(&x)
    说将内存位置“&x”解释为T*
考虑以下几点:

struct A1 { int a1; };
struct A2 { int a2; };
struct B : public A1, public A2 {};

void foo (A1 * a1, A2 * a2)
{
  B * b1_a1 = static_cast<B*> (a1);
  B * b2_a1 = reinterpret_cast<B*> (a1);
  B * b1_a2 = static_cast<B*> (a2);
  B * b2_a2 = reinterpret_cast<B*> (a2);

  std::cout << "b1_a1==b1_a2" << (b1_a1==b1_a2) << std::endl;
  std::cout << "b2_a1==b2_a2" << (b2_a1==b2_a2) << std::endl;
}

int main ()
{
  B b;
  foo (&b, &b);
}
这显示了从
a2
b2
static\u cast
如何正确地调整指针,使其指向
b
的开头,但是
重新解释cast
没有。

我的正常建议:

reinterpret\u cast
只能作为最后手段使用。你告诉编译器扔掉所有的警告,“删除所有的安全”,相信你的话,不管编译器对代码了解多少,它都是正确的。你应该只在没有其他办法的时候使用它

如果代码正确,在某些地方它们可能具有相同的效果。如果您最终做出更改并引入错误,而强制转换不再正确,
static\u-cast
可能会捕捉到它,但
reinterpret\u-cast
肯定不会

在这个非常特殊的场景中,最后一个参数没有那么重要:API将语义强加给您;它们是很好理解的语义;你正在铸造一个(空*)

尽管如此,我还是会使用
static\u cast
,并将
reinterpret\u cast
留给那些真正非同寻常的环境迫使我绕过类型安全的地方。由于API的C兼容特性,这是一个“正常”强制转换


(有关静态强制转换和重新解释强制转换之间区别的更多详细信息,请参见)

每个人都注意到重新解释强制转换比静态强制转换更危险。
这是因为reinterpret_cast忽略所有类型信息,只分配一个新类型而不进行任何实际处理,因此所完成的处理是实现定义的(尽管指针的位模式通常是相同的)

每个人都没有提到的一点是,reinterpret_cast是记录您的程序的一种手段。它告诉正在阅读代码的人,我们不得不妥协一些东西,结果我们的演员阵容很危险,当你弄乱这段代码时要小心

使用reinterpret_cast突出显示代码中的这些危险区域

从空隙*进行铸造时,没有可供铸件使用的类型信息。
因此,您要么执行无效的强制转换,要么将其强制转换回先前被强制转换为void*的原始类型。任何其他类型的铸造最终都会出现一些未定义的行为


使用reinterpret_cast作为标准可以保证使用reinterpret_cast将指针转换为void*并返回到其原始类型。通过使用reinterpret_cast,您可以向后遗症患者指出,这里正在发生一些不好的事情。

您应该真正做到win32文档中所说的正确的事情。这是最有可能起作用的,也最有可能是向前兼容的,除非我认为它的作者是完全无知的


更新:我已经查过了。Win32文档使用C样式转换。在这种情况下,C++定义了一个C样式的CAST来执行<代码>静态的铸件< /代码>。因此,正确的答案是:使用
static\u cast
。或者C风格的演员阵容,但通常最好避免使用。

Dupe:我讨厌这种笼统的说法,这是不对的。静态_cast仅在执行应用于的cast时才可取。reinterpret_cast应用于所有危险的强制转换,以便您可以在代码中快速找到它们。在两种指针类型(如果它们不相关)之间进行强制转换是一种重新解释强制转换操作。如果存在关系,那么静态_cast可能更合适。在这个问题的背景下,我会使用重新解释,因为你是从一个空*铸造。使用reinterpret_cast可以很好地说明这是一个潜在的危险类型(事实就是这样)。好吧,那么静态_cast可以用于哪些类型的类型,这些类型都是不安全的?静态_cast用于具有某种定义含义的强制转换,通常意味着相当安全。但是,标准保证将对象从指针强制转换为void*,然后再转换回相同的指针类型,以便重新解释_cast。所以这个p
g++ -o t t.cc ; ./t
b1_a1==b1_a2: 1
b2_a1==b2_a2: 0