根据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 ++提供的函数进行演员表?
答案 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
(无符号)。此外,WPARAM
,LPARAM
和LRESULT
也是指针大小的,因为窗口消息通常需要处理指针。
所以继续使用那个C风格的演员或reinterpret_cast<>
,无论你喜欢哪一个。其他强制转换不起作用,因为你需要将一个整数解释为一个指针,其他的强制转换不会让你这样做。
你可能还需要这些,因为还有其它的地方,因为Windows API不仅需要在C语言中,而且还可以从其他语言中使用,所以子类化被替换为将struct的对象作为第一个派生而来衍生结构的元素。这在WM_NOTIFY
消息中最为明显,其中所有可能的通知结构都使用NMHDR
执行此操作。请记住这一点。