回调函数的小结

来源:互联网 发布:数据库的储存过程 编辑:程序博客网 时间:2024/05/20 05:24

最近在实现一个窗口类时,需使用到回调函数实现与其他窗口类的通信交互,初次使用,查阅了一些资料,在此做小结,以方便以后使用回调函数的朋友。

什么是回调函数

简而言之,回调函数就是一个通过函数指针调用的函数。如果你把函数的指针(地址)作为参数传递给另一个函数,当这个指针被用为调用它所指向的函数时,我们就说这是回调函数。

为什么要使用回调函数?

  因为可以把调用者与被调用者分开。调用者不关心谁是被调用者,所有它需知道的,只是存在一个具有某种特定原型、某些限制条件(如返回值为int)的被调用函数。
也有这样的说法(比较容易理解):回调函数就好像是一个中断处理函数,系统在符合你设定的条件时自动调用。为此,你需要做三件事:1. 声明;2. 定义;3. 设置触发条件,就是在你的函数中把你的回调函数名称转化为地址作为一个参数,以便于DLL调用。

牛人理解:

回调函数实际上就是在调用某个函数(通常是API函数)时,将自己的一个函数(这个函数为回调函数)的地址(函数指针)作为参数传递给那个函数。而那个函数在需要的时候,利用传递的地址调用回调函数,这时你可以利用这个机会在回调函数(自己写的这个函数)中处理消息或完成一定的操作。简单的说就是回调函数函数不是系统定义的,而是应用程序自己定义的一个由系统来调用的函数,所以显然,它的参数必须按照约定来,即,参数是预先定义好的。

首先你要明白什么是函数指针。通过函数指针,可以得到函数所在的内存位置,从而执行该函数。在正常的程序执行过程中,调用方一般都是遇到函数就立即执行。而回调函数则是调用方通过函数指针的形式把函数储存起来。这样在合适的实际调用方就可以通过这个函数指针执行某个功能。回调函数可以说是一种订阅、分发的机制。被调用方可以通过订阅的形式将自己的处理函数以函数指针的形式交给调用方。当调用方需要执行这个回调函数的时候,就会通过分发的形式回调被调用方。回调函数的机制可以说无处不在,比如Channie Liu 所说的MFC消息机制,再比如HOOK,等等都是通过回调函数机制来执行的。但是回调函数并不是系统独有的机制。你完全可以在自己的程序中通过函数指针来实现一套回调函数。还有回调函数并不是面向对象编程,在某些情况下可以使用观察者模式来代替它。在.net中已经使用是事件的方式代替了回调函数来实现消息相应。简单说就是和Windows消息机制配套的,如果你有个消息循环响应机制,就必须要有这个回调函数,来统筹管理和响应消息,建议你看看Windows programing 5th的第一个例子程序就明白了。

在C++的TR1中(Technology Report)中包含一个function模板类和bind模板函数,使用它们可以实现类似函数指针的功能,但却却比函数指针更加灵活,特别是函数指向类 的非静态成员函数时。可以参考Scott Meyers. <<Effective C++ (3rd Edition)>>. Item 35.下面具体说明其使用方法。

实例见下:

#include "stdafx.h"
#include <iostream>
#include <functional>
#include <memory>


using namespace  std;


typedef std::tr1::function<void (int, int ,int)> UpdatePosEvent;


void Update1(int x, int y, int z)
{
cout<<x<<","<<y<<","<<z<<endl;
}


void Update2(int x, int y, int z)
{
cout<<2*x<<","<<2*y<<","<<2*z<<endl;
}


class T
{
public:
T(int times):nTimes(times)
{};
~T(){};


void Update(int x, int y, int z)
{
cout<<nTimes*x<<","<<nTimes*y<<","<<nTimes*z<<endl;
}


protected:
int nTimes;
};


int _tmain(int argc, _TCHAR* argv[])
{
UpdatePosEvent t1 = std::tr1::bind(&Update1,std::tr1::placeholders::_1,std::tr1::placeholders::_2,
std::tr1::placeholders::_3);




t1(1,2,3);


t1 = std::tr1::bind(&Update2,std::tr1::placeholders::_1,std::tr1::placeholders::_2,
std::tr1::placeholders::_3);


t1(1,2,3);


T a(10);


t1 = std::tr1::bind(&T::Update, &a, std::tr1::placeholders::_1,std::tr1::placeholders::_2,
std::tr1::placeholders::_3);

t1(1,2,3);






return 0;
}
0 0
原创粉丝点击