zoukankan      html  css  js  c++  java
  • 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.
    ",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;
    }
  • 相关阅读:
    poj 3310(并查集判环,图的连通性,树上最长直径路径标记)
    poj 3308(最小点权覆盖、最小割)
    poj 3281(网络流+拆点)
    poj 3275(传递闭包)
    poj 3204(最小割)
    poj 3164(最小树形图)
    poj 2987(最大权闭合图+割边最少)
    poj 2455(二分+最大流)
    poj 2391(二分+最大流)
    poj 2135(最小费用最大流)
  • 原文地址:https://www.cnblogs.com/xietianjiao/p/12890194.html
Copyright © 2011-2022 走看看