回调函数

关于这个东西,网上的教程真的太多了。这里我记录一个我觉得勉强有意思的,理解从理解函数指针到回调函数的过程。回调函数可以做很多东西,比如实现工厂模式,反射机制啊,某些种类的单例模式都可能用到。
反正挺无聊的。

1.理解函数指针

比如我要定义一个返回值为int 参数为(int, void*)的函数指针,一般都有三种写法

      typedef int(*func)(int,void *);//1
      using func = int(*)(int, void *);//2
      using func = std::function(int(int, void *));//3

推荐使用第3中定义。这里可以不用加void*这个参数,我们先理解下函数指针。

#include <iostream>
#include <functional>

using func = std::function<int (int)>;

int getPow(int i){
    return i*i;
}
int main(){
    func f = getPow;
    std::cout << f(6) << std::endl;
    return 0;
}

输出结果:

36

看了这个示例可能就知道什么是函数指针了,我们重点不是这个。

2.面向过程,注册函数指针

先定义一个全局的函数指针,然后写一个注册函数,然后调用这个注册的函数。

#include <iostream> 
#include <functional>

using func = std::function<int(int,void *)>;
func g_f;

void registPowCallBack(func f, void *ctx){
    g_f = f;
}

int getPow(int i, void *){
    return i*i;
}

int main(){
    registPowCallBack(getPow,nullptr);
    std::cout << g_f(5,nullptr) << std::endl;
    return 0;
}

运行结果

25

3. 面向对象的CallBack

调用可分传递的是函数指针还是对象指针

3.1 传递对象指针

我们这样定义A类是计算,B类用于打印信息。我们在A中注册B的对象指针,这里我在B中定义string name标志是那个B的实例。在A中调用B进行打印。

#include <iostream>
#include <functional>
#include <string>

using func = std::function<int(int,void *)>;
/*
* define class B to print data
*/
template <typename T>
class B{
  public:
    explicit B(std::string name):name_(name){}
    B(const B& )=delete;
    void pritnData(T i){
        std::cout << "by "<< this->name_ <<" "<<"the data is "<< i << std::endl;
    }
  private:
    std::string name_;
};

template <typename T>
class A{
public:
  explicit A(){};
  A(const A& ) = delete;
private:
int getPow(int i, void *ctx){
        B<T> *b = reinterpret_cast<B<T>*> (ctx);
        if (nullptr != b){
             b->pritnData(i*i);
        }
        return i*i;
    }
public:
  void regist_B_ptr(B<T>* b_ptr){
      b_ = b_ptr;
      //b_->pritnData(7);
    }

public:
  int getPow_A(int i){
      return getPow(i,b_);
  }
  

private:
   B<int>* b_;

};


int main()
{

    A<int>* a =new A<int>();
    B<int>* b =new B<int>("this_B_00");
    //b->pritnData(6);
    a->regist_B_ptr(b);
    a->getPow_A(2);
    delete a;
    delete b;
    return 0;
}

4.利用回调机制实现static成员函数,对非静态成员函数或非静态成员的使用

#include <iostream>
#include <functional>

using func = std::function<int(int,void *)>;
//func g_f;
void callBack(func f, void* ctx){
    //g_f = f;
    std::cout<<f(5,ctx) << std::endl;
}
class A{
public:
    static int getPow(int i, void* ctx){
        A *a = reinterpret_cast<A*>(ctx);
        return a->get_pow_impl(i);
    }
private:
    int get_pow_impl(int i){
        return i*i;
    }
public:
    //注册
    void regist(){
        callBack(getPow,this);
   }
private:
    int num_ = 5;
};
int main(){
    A* a = new A();
    a->regist();
    delete a;
    return 0;
}

5 常见的callback写法

class A{
public:
      //设置Callback函数到底是啥函数
      void SetCallback(std::function<void(Event)> func){
            event_callback_ = func;
      }
protected:
      //当已经设置了好了函数,调用的执行方法
      void Callback(Event event) {
        if (event_callback_) event_callback_(event);
     }
private:
      //声明callback 函数指针
       std::function<void(Event)> event_callback_ = nullptr;
};
posted @ 2020-08-20 16:41  cyssmile  阅读(166)  评论(0编辑  收藏  举报