春暖花开
雪化了,花开了,春天来了
posts - 149,comments - 125,trackbacks - 0
 

最近在看代码,写代码的人很喜欢用回调函数和函数指针。一直觉得回调函数和函数指针挺神秘的,所以查了一些资料,来与大家一起来分享。

什么是回调函数

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

为什么要使用回调函数

   因为使用回调函数可以把调用者和被调用者分开,调用者不关心谁是被调用者,所有它需知道的,只是存在一个具有某种特定原型、某些限制条件(如返回值为int)的被调用函数。回调函数就好像是一个中断处理函数,系统在符合你设定的条件时自动调用。

如何使用回调函数

 使用回调函数,我们需要做三件事:

  • 声明
  • 定义
  • 设置触发条件:在你的函数种把你的回调函数名称转化为地址作为一个参数,以便于系统调用。

声明和定义时应注意,回调函数由系统调用,所以可以认为它属于windows系统,不要把它当作你的某个类的成员函数。

回调函数是一个程序员不能显示调用的函数,通过将回调函数的地址传给调用者从而实现调用。回调函数是十分必要的,在我们想通过一个统一接口实现不同的内容,这时回调函数非常合适。

函数指针的声明

对回调函数有了一个初步的了解,下面我们来说一下函数指针。因为要实现回调,必须首先定义函数指针。

void (*) ()

左边圆括弧中的星号是函数指针声明的关键。另外两个元素是函数的返回类型(void)和右边圆括弧中的入口参数

为函数指针声明类型定义:

Typedef void(* pfv)()

pfv 是一个函数指针,它指向的函数没有输入参数,返回类型为voie。使用这个类型定义名称可以隐藏负责的函数指针语法。

void (*p)();

void func()

{

……

}

p = func;

p的赋值可以不同,但一定要是函数的指针,并且参数和返回类型相同。

例如:

现学现卖的一个小例子

#include <iostream>
using namespace std;

typedef 
void (*PF)();
void func()
{
  cout 
<< "func" << endl;
}


void caller( PF pf)
{
  pf();
}


int main()
{
  PF p 
= func;
  caller(p);

  system(
"pause");

  
return 0;
}


调用约定

visual c++中,可以在函数类型前加_cdecl,_stdcall或者_pascal来表示调用规范(默认为_cdecl)。调用规范影响编译器产生的给定函数名,参数传递的顺序,堆栈清理责任以及参数传递机制。

不过,在win32的程序中,我见得比较多的是CALLBACK,这个宏定义在windef.h中,

#define CALLBACK    __stdcall

它约定了函数在它们返回到调用者之前,都会从堆栈中移除掉参数。

 

摘自:

回调函数

http://hi.baidu.com/spidermanzy/blog/item/b25b00956469c6097bf48016.html

回调函数以及钩子函数的概念

http://zq2007.blog.hexun.com/9068988_d.html

声明函数指针并实现回调

http://www.vckbase.com/document/viewdoc/?id=195

posted on 2008-12-07 16:56 Sandy 阅读(13196) 评论(7)  编辑 收藏 引用 所属分类: windows学习

FeedBack:
# re: 回调函数和函数指针
2008-12-07 20:10 | 肥仔
good.
回调函数和函数指针是低阶的技术特性。
一个建议是,可以在此基础上,更进一步,学习理解“委托”这种基于回调的高阶编程思想,将得到更多。。。。。。
  回复  更多评论
  
# re: 回调函数和函数指针
2008-12-07 20:13 | 肥仔
# re: 回调函数和函数指针
2008-12-07 22:33 | 沈臻豪(foxtail)
肥仔好厉害哦  回复  更多评论
  
# re: 回调函数和函数指针[未登录]
2008-12-08 08:47 | SpringSnow
@肥仔
谢谢 肥仔了!学习了
:)
  回复  更多评论
  
# re: 回调函数和函数指针
2008-12-11 13:49 | jmchxy
你天天在使用回调函数. 基本上GUI界面底层都是回调函数处理的. 典型的就是Windows系统的窗口处理还是 winproc  回复  更多评论
  
# re: 回调函数和函数指针
2008-12-11 13:58 | jmchxy
事实上回掉函数和普通函数是没区别的. 你同样可以使用定义的回调函数做其它事情. 调用约定是有调用者规定的(函数参数中规定了回调函数的类型, 函数类型包括了函数的调用约定, 参数, 返回值), CALLBACK 是 win16 一个遗留宏定义, 当初是定义成的 pascal 约定, 现在都是定义成 WINAPI宏, 使用的是 __stdcall 约定.
类静态成员函数可以作回调函数, 不用成员函数做回调函数的原因是成员函数的参数比参数表中列出的多了一个this指针(其实也是可以用的, 那种技巧没什么好处就是了,呵呵)  回复  更多评论
  
# re: 回调函数和函数指针
2008-12-14 16:55 | Sandy
@jmchxy
说的很对。在windows系统的窗口处理本身就是回调函数,虽然天天在用,对其机制不是很了解。所以jmchxy的补充让我很受益。
谢谢!  回复  更多评论
  

只有注册用户登录后才能发表评论。
网站导航: 博客园   IT新闻   BlogJava   博问   Chat2DB   管理