一、前言
什么是回调函数?各类语言中都存在回调函数,C语言和C++一系列语言中通过回调机制实现模块化、多态化、不同模块的参数传递。
回调机制,c语言和c++的回调机制主要通过函数指针来实现。
typedef T(*PFuncCallback)(T1 param1,T2 param2);
二、c语言多态例子
//声明回调类型函数PSayHelloCallback //@void 为返回来兴 //@name 参数一,表示名字 //@context 上下文,c语言中一般为nullptr typedef void(*PSayHelloCallback)(const char * name,void * context); //定义一个函数指针实体 PSayHelloCallback phelloCallback; void SayHelloEnglish(const char* name,void * context) { printf("Hello,I'm %s. ",name); } void SayHelloChinese(const char* name, void * context) { printf("你好,我是%s。 ", name); } void RegistCallFunc(PSayHelloCallback phello) { phelloCallback = phello;
调用
RegistCallFunc(SayHelloEnglish); //通过函数指针,把所需的函数传入,通过一个全局指针实现,可以实现c语言的多态,根据需要调用 phelloCallback("lilei",nullptr); RegistCallFunc(SayHelloChinese); phelloCallback("李雷", nullptr);
三、C语言传参的例子
///传值例子 //库提供方的函数指针 typedef void(pOutputCallback)(int ra); //库提供方提供的函数 void PrintINT(pOutputCallback pOut) { pOut(5); } void Output(int ra) { printf("数字是%d ",ra); } 主函数中 PrintINT(Output); //通过函数指针把外部定义的函数,传入调用方供调用方调用,所以称回调,函数外部定义解析,这样就可以实现接收库提供的数据
四、c++回调函数的实现
对于c++,是面向对象的语言,回调的时候,是哪个实体?所以需要注册回调的时候传入对象实例;c++具有封装性,本类内的回调是没有意义的,所以需要把回调函数设置成静态成员函数或者友元函数。
typedef void(*PFucnCallback)(string name,void* context); class CPerson { public: CPerson() {} ~CPerson() {} CPerson(int age,string name); void PrintInfo(); static void OnSayHello(string name, void* context) { cout << "hello world!I'm"<<name<<"." << endl; } void RegistCallback(PFucnCallback pf,void* context); private: int m_age; string m_name; }; CPerson::CPerson(int age, string name){ m_age = age; m_name = name; } void CPerson::PrintInfo() { cout << "我叫" << m_name << ",我今年" << m_age << "岁。" << endl; } //由于静态函数不能访问类成员,回调传入的对象要在此解析,解析后调用回调函数 void CPerson::RegistCallback(PFucnCallback pf, void* context) { CPerson* person = (CPerson*)context; if (person) pf(person->m_name, nullptr); } int main() { CPerson *person = new CPerson(10,"李明"); CPerson *person2 = new CPerson(11, "小文"); //需要显示谁的成员,就传入谁,类似的友元函数也能实现赐个回调 //友元函数实现只能自身的对象调用,比静态函数实现具有局限性 person->RegistCallback(CPerson::OnSayHello, person2); std::getchar(); return 0; }
五、c++11回调函数的实现
c++11引入了bind函数,它在functional头文件中,与之匹配的承接者可以用funciton()来构造,实际中使用auto就可以了。
class CPerson { public: CPerson() {} ~CPerson() {} CPerson(int age,string name); void PrintInfo(); private: int m_age; string m_name; }; CPerson::CPerson(int age, string name){ m_age = age; m_name = name; } void CPerson::PrintInfo() { cout << "我叫" << m_name << ",我今年" << m_age << "岁。" << endl; } int main() { CPerson *person = new CPerson(10,"李明"); CPerson *person2 = new CPerson(11, "小文"); //callback 的实际类型是function(void(void)),auto是推导 //function 实际是一个函数指针,可以承接函数,lambd表达式,其他可调用对象 //std::placeholders标识占位符号 auto callback = bind(&CPerson::PrintInfo,person); callback(); std::getchar(); return 0; }