混淆C++铸造
我一直在阅读很多关于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;
}
}
...
}
如果这也不行,那我将如何只使用静态,动态和/或const铸造LPARAM值转换为指针?
另外:如果reinterpret_cast的是不可移植的,我怎么会重写它是便携式的(良好做法)
使用的reinterpret_cast是可以接受的,如果你知道指针最初目标类型。任何其他用途都利用了依赖于实现的行为,尽管在许多情况下这是必要且有用的,例如将指向结构的指针转换为指向字节的指针,以便可以对其进行序列化。
它被认为是危险的,因为它不会在编译时或运行时检查。如果你犯了一个错误,它会崩溃并烧毁,而且很难调试。你基本上告诉编译器“我比你更了解这个实际情况,所以只需编译代码,让我担心后果。”
以这种方式序列化结构是一个坏主意(即使经常完成),但这是另一个问题的主题。 – Tronic 2010-02-27 01:50:06
你看到它在MSDN的原因是因为Win32 API是ç API,但人们坚持让步C++例子。
当您编写与其他库接口的代码时,重新解析转换是很好的。应该在您自己的应用程序内避免。
不是不尊重MSDN,但MSDN不是适合C++编码的最佳选择。
使用reinterpret_cast的一个原因是当您向/从不透明数据类型转换/时。 reinterpret_cast不是“危险的”,它只是很容易搞砸并导致代码中的问题,这就是为什么它应该被避免。
为什么C++风格强制类型首选的原因是,static_cast是类型安全的,并且所有强制转换时间都更容易搜索。
程序员[不正确]经常使用强制转换来“摆脱编译器警告”,如从无符号转换为有符号整数,或者从32位整数转换为8位整数。
+1。 MSDN充满了MS-ISMS。 Scott Meyers和Herb Sutter的好书(尽管他现在在MS,他是一位出色的作家,并且在编写优秀的C++方面有很多伟大的建议)是巩固自己对良好C++实践的理解的好地方。 – 2010-02-27 01:15:37
@Matt Curtis - 我觉得MSDN中比较烦人的部分是MS-isms不一致的应用。他们的例子质量差异很大。但一般来说,你不应该复制他们的例子;它可能会给你一个粗略的想法,但你应该将这些想法适应于你正在使用的项目中使用的任何编码风格。 – asveikau 2010-02-27 01:53:59
本质reinterpret_cast
是“安全”与C结构和基本类型(霸菱平原错误,类似于铸造int
的指针和背部,这在ILP32架构,但在LP64一个休息的作品。)AC结构不会有任何东西,除了可能用于对齐的填充,您没有声明。之类的东西指向虚表和指向虚基类 -
reinterpret_cast
因为编译器插入数据项到你的类不能与C++多态类型安全。其他C++类型转换可以在从指针向基类向指向派生类的指针下注时调整这些值,reinterpret_cast
和C风格类型转换不会。
这是一个使用C++编程Windows平台SDK(C API)的示例。该窗口过程只有WPARAM和LPARAM参数,并且如果需要通过窗口消息将指针传递给结构,则必须进行强制转换。在我看来,这是reinterpret_cast <>的完全可接受的用法。您无法避免投射,因为您要写入的SDK不是您的代码,并非针对C++设计的,更不用说类型安全性,并且需要使用C绑定来提供泛型参数类型。
reinterpret_cast <>这里是一个标志,让你知道你需要小心,但它不是不惜一切代价避免。
另一方面,如果您控制代码的双方,API和消费者,那么最好制作一个类型安全的API,并且不需要消费者执行强制转换以使用它正确。
这可能是非常旧的代码库。 – 2010-02-27 00:50:48