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