明确一点即回调函数须要是静态函数。缘由:编程
若不想使用C式函数做为回调函数呢?(破坏封装性)函数
下面讲解一下第二点,我认为比较好用。this
class A { public: static void staticmember(){cout<<"static"<<endl;} //static member void nonstatic(){cout<<"nonstatic"<<endl;} //nonstatic member virtual void virtualmember(){cout<<"virtual"<<endl;};//virtual member }; int main() { A a; //static成员函数,取得的是该函数在内存中的实际地址,并且由于static成员是全局的,因此不能用A::限定符 void (*ptrstatic)() = &A::staticmember; //nonstatic成员函数 取得的是该函数在内存中的实际地址 void (A::*ptrnonstatic)() = &A::nonstatic; //虚函数取得的是虚函数表中的偏移值,这样能够保证能过指针调用时一样的多态效果 void (A::*ptrvirtual)() = &A::virtualmember; //函数指针的使用方式 ptrstatic(); (a.*ptrnonstatic)(); (a.*ptrvirtual)(); }
直接用类名引出非静态成员函数,赋值给函数指针:.net
//nonstatic成员函数 取得的是该函数在内存中的实际地址 void (A::*ptrnonstatic)() = &A::nonstatic;
随后须要运行回调函数的时候,使用一个辅助变量来运行,格式为:(变量名. * 函数指针)(参数)。指针
(a.*ptrnonstatic)();
若是在咱们的编程过程当中:code
咱们可使用:blog
bool (DoTask::*function)(void *arg);
其中DoTask是一个类名,上面写的就是一个返回值为bool类型,参数为void *类型的函数指针,指向DoTask这个类中的成员函数。内存
而后调用的时候咱们能够:作用域
Dotask d; //注意ReadData函数不用加括号,要加做用域和地址符 bool (DoTask::*function)(void *arg) = &DoTask::ReadData; (d.*function)(NULL);
注意点就是赋值给函数指针的时候须要取地址符、加做用域、函数不加括号,直接函数名便可。get
调用的时候,用一个实例去调用函数指针便可。
假如咱们将函数指针放在一个结构体中:
struct task { bool (DoTask::*function)(void *arg); void *arg; };
那么咱们调用它的时候也是同样的。
struct task t; t.function = &DoTask::ReadData; ... DoTask d; (d.*(t.function))(NULL); //完成调用。
如今看调用这一步。参照上面的:
(d.*function)(NULL)
只不过function如今存在结构体中,替换成从结构体中取出来便可:
function 替换成 t.function
代入便可。