注:与tr1::function对象结合使用,能得到更好的效果,详情见http://blog.csdn.net/this_capslock/article/details/38564719程序员
回调函数是基于C编程的Windows SDK的技术,不是针对C++的,程序员能够将一个C函数直接做为回调函数,可是若是试图直接使用C++的成员函数做为回调函数将发生错误,甚至编译就不能经过。 编程
普通的C++成员函数都隐含了一个传递函数做为参数,亦即“this”指针,C++经过传递一个指向自身的指针给其成员函数从而实现程序函数能够访问C++的数据成员。这也能够理解为何C++类的多个实例能够共享成员函数可是确有不一样的数据成员。因为this指针的做用,使得将一个CALLBACK型的成员函数做为回调函数安装时就会由于隐含的this指针使得函数参数个数不匹配,从而致使回调函数安装失败。函数
这样从理论上讲,C++类的成员函数是不能看成回调函数的。但咱们在用C++编程时总但愿在类内实现其功能,即要保持封装性,若是把回调函数写做普通函数有诸多不便。通过网上搜索和本身研究,发现了几种巧妙的方法,可使得类成员函数看成回调函数使用。this
这里采用Linux C++中线程建立函数pthread_create举例,其原型以下:spa
类MyClass须要在本身内部开辟一个子线程来执行成员函数func()中的代码,子线程经过调用startThread()成员函数来启动。这里将回调函数callback写在了类外面,传递的参数是一个指向MyClass对象的指针(在pthrad_create()中由第4个参数this指定),回调函数通过强制转换把void*变为MyClass*,而后再调用arg->func()执行子线程的代码。.net
这样作的原理是把当前对象的指针看成参数先交给一个外部函数,再由外部函数调用类成员函数,之外部函数做为回调函数,但执行的是成员函数的功能,这样至关于在中间做了一层转换。缺点是回调函数在类外,影响了封装性,这里把callback()限定为static,防止在其它文件中调用此函数。线程
方法二:回调函数为类内静态成员函数,在其内部调用成员函数指针
在方法一上稍做更改,把回调函数搬到类MyClass里,这样就保持了封装性。代码以下:rest
类MyClass有了1个静态数据成员CurMy和1个静态成员函数callback。CurMy用来存储一个对象的指针,充当方法一中回调函数的参数arg。callback看成回调函数,执行CurMy->func()的代码。每次创建线程前先要调用setCurMy()来让CurMy指向当前本身。code
这个方法的好处时封装性获得了很好的保护,MyClass对外只公开一个接口startThread(),子线程代码和回调函数都被设为私有,外界不可见。另外没有占用callback的参数,能够从外界传递参数进来。但每一个对象启动子线程前必定要注意先调用setCurMy()让CurMy正确的指向自身,不然将为其它对象开启线程,这样很引起很严重的后果。
方法三:对成员函数进行强制转换,看成回调函数
代码以下:
这个方法是原理是,MyClass::func最终会转化成 void func(MyClass *this); 也就是说在原第一个参数前插入指向对象自己的this指针。能够利用这个特性写一个非静态类成员方法来直接做为线程回调函数。对编译器而言,void (MyClass::*FUNC1)()和void* (*FUNC)(void*)这两种函数指针虽然看上去很不同,但他们的最终形式是相同的,所以就能够把成员函数指针强制转换成普通函数的指针来看成回调函数。在创建线程时要把当前对象的指针this看成参数传给回调函数(成员函数func),这样才能知道线程是针对哪一个对象创建的。
方法三的封装性比方法二更好,由于不涉及多个对象共用一个静态成员的问题,每一个对象能够独立地启动本身的线程而不影响其它对象。
暂时就列出这些方法,之后发现更好的再来补充,over
http://blog.csdn.net/this_capslock/article/details/17001003
---------------------------------------------------------------------------------------