将DWORD_PTR转换为类,反之亦然,无需c样式转换

时间:2016-11-12 22:42:06

标签: c++ winapi visual-studio-2015

根据Herb Sutter的C++ Coding Standards: 101 Rules, Guidelines, and Best Practices程序员应该避免使用c风格的演员:

  

C风格的强制转型具有不同(通常是危险的)语义,具体取决于上下文,所有这些都伪装成单一语法。用C ++样式转换来替换C风格的强制转换有助于防止意外错误

我正在尝试将指针int a[] = {5, 1, 4, 8, 17, 12, 22}; int b[] = {2, 4, 3, 4, 11, 13, 17}; int max = Arrays.stream(b).max().getAsInt(); int c[] = new int[max+1]; int d[] = new int[max+1]; int e[] = new int[a.length]; for(int i=0;i<b.length;i++){ c[b[i]]=1; } for(int i=1;i<c.length;i++){ d[i] = d[i-1] + c[i]; } for (int i = 0; i<a.length;i++){ e[i]=(a[i]>max)?d[d.length-1]:d[a[i]-1]; } System.out.println(Arrays.toString(a)); System.out.println(Arrays.toString(b)); System.out.println(Arrays.toString(c)); System.out.println(Arrays.toString(d)); System.out.println(Arrays.toString(e)); 传递给WinAPI回调函数,为此我想使用回调函数的DWORD_PTR参数(下面的示例正在工作,但包含C风格的强制转换):

p_ctrl

我已经尝试过动态转换,但这给了我错误。 WndCtrls* WndCtrls::Button ( WndCtrls* const p_ctrl, HWND hwnd, RECT const &rc ) { p_ctrl->ctrl = CreateWindowEx ( 0, L"BUTTON", p_ctrl->w_classNameButton.c_str (), WS_VISIBLE | WS_CHILD | BS_OWNERDRAW, rc.left, rc.top, rc.right, rc.bottom, hwnd, 0, (HINSTANCE)GetWindowLongPtr ( hwnd, GWL_HINSTANCE ), // Problematic C-style cast for which I already know workaround p_ctrl ); SetWindowSubclass ( p_ctrl->ctrl, WndCtrls::CtrlProc, 0, (DWORD_PTR)p_ctrl ) ) // C-style cast return p_ctrl; } LRESULT CALLBACK WndCtrls::CtrlProc ( HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam, UINT_PTR uIdSubclass, DWORD_PTR dwRefData ) { WndCtrls* const p_ctrl = (WndCtrls*)dwRefData; // Problematic C-style cast switch ( message ) { ... } return DefSubclassProc ( hwnd, message, wParam, lParam ); } 根本不应该使用(根据Sutter的说法)。

请问有没有办法使用c ++提供的函数进行演员表?

1 个答案:

答案 0 :(得分:4)

Sutter的建议就是:建议。它们不是硬性规定;它们只是鼓励您编写更安全,更强大的代码的建议。

这是建议不起作用的情况之一。

在许多地方,Windows API需要能够传递可能或可能不是指针的数据。因此,它使用指针大小的整数,使用C样式转换(请记住,Windows API主要是基于C的)将整数转换为指针。这个安全的,因为文档要求它是:如果你给Windows一个垃圾指针值,你就违反了该函数的规则!

指针大小的整数的标准C / C ++名称是intptr_t(有符号)和uintptr_t(无符号)。但是,Windows早于C99和C ++ 11(当引入它们时),因此它使用自己的名称:LONG_PTR(已签名)和DWORD_PTR以及ULONG_PTR(无符号)。此外,WPARAMLPARAMLRESULT也是指针大小的,因为窗口消息通常需要处理指针。

所以继续使用那个C风格的演员或reinterpret_cast<>,无论你喜欢哪一个。其他强制转换不起作用,因为你需要将一个整数解释为一个指针,其他的强制转换不会让你这样做。

你可能还需要这些,因为还有其它的地方,因为Windows API不仅需要在C语言中,而且还可以从其他语言中使用,所以子类化被替换为将struct的对象作为第一个派生而来衍生结构的元素。这在WM_NOTIFY消息中最为明显,其中所有可能的通知结构都使用NMHDR执行此操作。请记住这一点。