【问题标题】:Use a non-class member as an event handler使用非类成员作为事件处理程序
【发布时间】:2017-05-09 13:00:10
【问题描述】:

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

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

class TMyClass {
  public:
    TMyEvent OnMyEvent;
};

void __fastcall myEventHandler(int index) { }

TMyClass myClass;
myClass.OnMyEvent = myEventHandler;

...问题来了:

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

无法将 void(int) 转换为 TMyEvent

我重用TMyClass 来生成不同类型的包装器,并且需要typedef 中的__closeure,因此它适用于VCL 表单项目。

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

【问题讨论】:

    标签: eventhandler c++builder-10.1-berlin


    【解决方案1】:

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

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

    class TMyEvents {
    public:
        void __fastcall myEventHandler(int index) { }
    };
    
    TMyClass myClass;
    TMyEvents myEvents;
    myClass.OnMyEvent = myEvents.myEventHandler;
    

    如果处理程序是独立函数,或者是类的静态方法,则必须在参数列表中显式提供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!不要尝试将它与其他类型的函数指针一起使用。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2017-06-04
      • 1970-01-01
      • 1970-01-01
      • 2021-04-10
      • 2011-03-05
      • 1970-01-01
      • 1970-01-01
      • 2013-12-24
      相关资源
      最近更新 更多