使用非 class 成员作为事件处理程序

Use a non-class member as an event handler

我正在为 C++Builder VCL 编写 DLL 包装器 class。这是一个极其简化的问题示例:

typedef void __fastcall (__closure *TMyEvent)(int index);

class TMyClass {
  public:
    TMyEvent OnMyEvent;
};

void __fastcall myEventHandler(int index) { }

TMyClass myClass;
myClass.OnMyEvent = myEventHandler;

...这就是问题所在:

通常myEventHandler是在另一个class中定义的,但在这里它被定义为一个全局函数。当我尝试将 myEventHandler 分配给 myClass.OnMyEvent 时,出现错误

Cannot convert void(int) to TMyEvent

我重复使用 TMyClass 来生成不同类型的包装器并需要 typedef 中的 __closeure 以便它与 VCL 表单项目一起工作。

__closure的问题吗?我可以使用全局函数作为事件处理程序吗?

__closure 编译器扩展是一种特殊类型的 class 方法指针,它包含两个指针 - 指向对象实例的指针和指向处理程序方法的指针。当执行 __closure 时,编译器通过其 this 参数将对象指针传递给处理程序。因此,处理程序必须有一个 this 参数。

如果处理程序是 class 的非静态成员,编译器会为您隐式处理 this 指针,例如:

class TMyEvents {
public:
    void __fastcall myEventHandler(int index) { }
};

TMyClass myClass;
TMyEvents myEvents;
myClass.OnMyEvent = myEvents.myEventHandler;

如果处理程序是独立函数,或者是 class 的静态方法,则必须在参数列表中显式提供 this 指针。在这种情况下,您可以使用 TMethod1 结构来帮助您将处理程序分配给事件,例如:

void __fastcall myEventHandler(void *Data, int index) { }

TMethod m;
m.Data = ...; // can be anything you want to pass to the 'Data' parameter
m.Code = &myEventHandler;

TMyClass myClass;
myClass.OnMyEvent = reinterpret_cast<TMyEvent&>(m);

1:这只适用于 __closure!不要尝试将它与其他类型的函数指针一起使用。