【发布时间】:2020-05-14 02:47:26
【问题描述】:
我处于在构造函数执行期间将指向成员函数的指针共享到外部的情况。并且可以随时调用成员函数,甚至在构造函数完成之前。我假设它可能导致未定义的行为。 这种情况出现在以下情况。
ButtonCtrl::ButtonCtrl(int id, HWND hwnd_parent, int x, int y,
int w, int h, const string& text)
{
this->hwnd = CreateWindowExW(0, L"BUTTON", this->wtext.c_str(),
WS_CHILD | WS_VISIBLE | WS_TABSTOP,
x, y, w, h, hwnd_parent, (HMENU)id,
GetModuleHandle(NULL), NULL);
this->wndproc_org = (WNDPROC) SetWindowLongW(this->hwnd, GWL_WNDPROC,
(LONG) &ButtonCtrl :: wndproc_new);
}
这里 wndproc_new 是静态类方法,但认为它不是静态的。现在在 SetWindowLongW 方法中,我将 Button 的窗口过程替换为我的窗口过程 (wndproc_new )。由于按钮已经使用 CreateWindowExW 创建,它的消息循环可能已经开始。现在它可以随时调用我的 wndproc_new。甚至在这个构造函数完成之前。所以我的问题是,我会得到未定义的行为还是有效?
【问题讨论】:
-
您可以在构造函数完成之前调用成员函数,前提是您不读取这些函数中未初始化的成员。
-
它不能在任何时候调用wndproc_new,在构造函数完成之前不能调用。因为窗口过程(回调)只能在几个 api 调用中调用(
GetMessage,PeekMessage..)。 -
作为旁注 - 需要使用
SetWindowLongPtrW和GWLP_WNDPROC,以及你的子类按钮是什么?为什么不通过SetWindowSubclass? -
现在它可以随时调用我的 wndproc_new。 - 这是错误的假设,无论如何你都没有 UB
-
@RbMm 我使用
SetWindowLongW因为我的目标是 32 位。我想具体而不是依赖宏观。同样,我没有声明 UNICODE 而是使用 W 或 A 函数。 无论如何你都没有 UB(?) ?