回调函数

来源:互联网 发布:mac qq截屏 编辑:程序博客网 时间:2024/05/29 18:40

C++编程过程中,常常使用回调函数的形式来通知某个类一个事件。例如,使用图形引擎实现了一个滚动条控件,当滚动条滚动的时候,需要通知其父窗口进行滚动,这时可以注册一个回调函数到滚动条类中接收滚动事件。

回调函数分两种:静态回调函数和类成员回调函数。其中静态回调函数比较常用,例如,我们定义如下静态函数指针:

typedef void(*Func)();

这个类型的函数指针,可以指向一个没有参数并且返回值为void的函数。在消息源中,我们定义如下函数指针变量:

         Func pf;

并且提供一些接口对这个变量进行赋值,当需要发送消息时,只需如下调用:

if(NULL != pf)

            pf();

这样就能发送消息给消息接收者了。

         在消息接收者一端,我们只要定义一个函数如下:

void MsgReceive();

即可接收消息。如果消息接收者是一个类,那么我们需要一个静态函数:

         class A

         {

         protected:

              static void MsgReceive();

};

但这样有一个问题,如果在消息接收函数中需要处理本类中的一些变量的状态,则因为是静态成员函数,而不能访问非静态成员。有一个解决办法是在消息接收函数中定义一个用户自定义参数,例如:

         typedef void(*Func)(LPARAM);

这个消息接收函数带一个自定义参数,消息接收类可以设置将自身的this指针存储其中,当接收消息时,由发送者返回这个参数。不过,这种方法需要在消息接收类中将自定义参数强制转换为本类指针,然后由该指针访问成员变量,不是很方便。

         还有另一个解决方案,就是使用类成员函数指针:

class SomeClass

{

public:

     void testFunc() {}

};

         typedef void(SomeClass::*Func)();

这时,我们在消息发送者中定义Func pf;并将pf赋值为&SomeClass::testFunc,然后提供一个接口传递SomeClass的一个实例指针(SomeClass* pobj),就可以使用pobjpf访问SomeClass::testFunc。访问方法如下:

         (pobj->*pf)();

这种方式,可以直接注册成员函数来接收消息,方便了不少。但是,由于Func定义为SomeClass的某个空参成员函数指针,如果我们有另一个类,也需要接收消息,就不好做了,因为Func只能指向SomeClass的一个成员函数,不能指向其他类的成员函数。

         为解决上述问题,很容易联想到使用模板,将Func定义为一个模板函数指针,于是我们“尝试”者写出如下代码:

         template<class T>

         typedef void(T::*Func)();

但是很不幸,C++不支持模板类型定义,具体原因请自行查询C++标准。

         那么没办法了么?我们可以绕开C++这一限制,即将消息发送者制作成模板类,如下所示:

在模板类中定模板函数是C++所允许的,模板参数T就是我们需要的消息接收者。怎么样,是不是能够方便很多呢?