c++的回调函数

一、前言

什么是回调函数?各类语言中都存在回调函数,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.\n",name);
}

void SayHelloChinese(const char* name, void * context) {

    printf("你好,我是%s。\n", 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\n",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;
}

 

posted @ 2020-05-14 17:36  卖雨伞的小男孩  阅读(1433)  评论(0编辑  收藏  举报