实现任意函数调用的代码
参考:https://www.jianshu.com/p/f191e88dcc80
1. std::function
- std::function 是一个可调用对象包装器,是一个类模板,可以容纳除了类成员函数指针之外的所有可调用对象,它可以使用统一的方式处理函数、函数对象、函数指针,并允许保存和延迟它们的执行。
- 定义格式:std::function<函数模板>
- std::function 可以取代函数指针的使用,因为它可以延迟函数的执行,特别适合作为回调函数使用。它比普通函数指针更加的灵活和便利。
2. std::bind
可将std::bind函数看作一个通用的函数适配器,它接受一个可调用对象,生成一个新的可调用对象来“适应”原对象的参数列表。
std::bind将可调用对象与其参数一起进行绑定,绑定后的结果可以使用std::function保存。
std::bind主要有以下两个作用:
- 将可调用对象和其参数绑定成一个防函数(防函数是啥需要再查查资料,哈哈)
- 只绑定部分参数,减少可调用对象传入的参数
下面是利用std::function, std::bind以及带参模板函数,实现的一段代码,这段代码可以保存任意“可调用对象”,并保存和延迟了他们的执行。非常适合用来作为各类回调函数的抽象接口。
include<functional> // std::function #include<utility> // std::forward class CallBack{ public: template<class F, class... Args> CallBack(F&& f, Args&&... args){ task = std::bind(std::forward<F>(f), std::forward<Args>(args)...); // std::forward 完美转发,实现了参数在传递过程中保持其值属性的功能,即若是左值,则传递之后 } // 仍是左值,若是右值,则传递之后仍是右值。 void Run(){ task(); } virtual ~CallBack(){} private: std::function<void()> task; // std::function 一种通用的多态函数包装器, std::function的实例可以存储、复制和调用任何可调用的目标(函数、lamda表达式、绑定表达式或其他函数对象,以及指>向成员函数的指针和指向数据成员的指针) }; template<class F, class... Args> CallBack* NewCallBack(F&& f, Args&&... args){ return new CallBack(f, args...); } class sample{ public: void func2(int a, int b){ a_ = a; b_ = b; printf("a=%d, b=%d\n", a_, b_); } void run(){ CallBack * cb2 = NewCallBack(&sample::func2, this, 200, 300); // 在类内部,传入成员函数时,需要传入this指针 cb2->Run(); } private: int a_; int b_; }; void func(){ printf("hello\n"); } void func1(int a){ printf("hello, %d\n", a); } int main(){ CallBack * cb = NewCallBack(func); CallBack * cb1 = NewCallBack(func1, 200); sample s; // CallBack * cb2 = NewCallBack(&sample::func2, &s, 200, 300); // 在内外部调用成员函数,需要传入对象的引用 cb->Run(); cb1->Run(); // cb2->Run(); s.run(); std::function<void()> f = std::bind(func1, 1); // 使用function<void()>和std::bind可以将各类函数统一成一个接口
// 运行时调用接口一样,非常易用于回调过程,简化了参数处理。 f(); return 0;
运行结果:
[daq@centos build]$ ./hello-exe/cmake-good hello hello, 200 a=200, b=300 hello, 1