1. 程式人生 > >std::function與回撥類

std::function與回撥類

std::function是c++11中提供的Callable類,所以本篇文章中整理了function的使用方式,及以function為基礎封裝回調類。
1. function的使用

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

int add(int a, int b)
{
    return a + b;
}

class EchoMessage
{
public:
    void echoMessage(const string& msg)
    {
        std
::cout << msg << std::endl; } } void test() { // 普通函式繫結 function<int(int, int)> f_add = &add; int sum = f_add(1, 2); // 物件成員函式繫結,注意收個函式為類物件引用或指標; function<void(EchoMessage&, const string&)> f_echo = &EchoMessage::echoMessage; EchoMessage em; f_echo(em, "Hello"
); // 引數繫結 function<void(const string&)> f_echo1 = bind(&EchoMessage::echoMessage, em, placeholders::_1); f_echo1("Hello"); }

2. 基於function的回撥類
通過將物件指標及成員函式指標儲存在回撥型別的成員中,在執行某個執行流中呼叫執行成員函式函式,即可實現函式的回撥。依據上述思路,參考muduo庫中的實現,對回撥類的封裝如下。注意執行回到函式的返回值為void。

#include <functional>
#include <iostream> #include <memory> using namespace std; template <typename Cls, typename... Args> class WeakCallback { public: // 將類指標,作為首個引數,構造function回撥; using callable = function<void(Cls*, Args...)>; // 入參弱指標型別,從外部接管物件,其生命週期與WeakCallback物件的宣告週期一致 WeakCallback(const weak_ptr<Cls>& ptr_obj, const callable& cb) : ptr_obj_(ptr_obj), cb_(cb) { } // 過載括號操作符 void operator()(Args&&... args) { // 此處必須轉換為shared_ptr,否則會導致弱指標退出作用域而被析構 shared_ptr<Cls> ptr_obj(ptr_obj_.lock()); if(ptr_obj) { cb_(ptr_obj.get(), std::forward<Args>(args)...); } } private: weak_ptr<Cls> ptr_obj_; callable cb_; }; template<typename CLASS, typename... ARGS> WeakCallback<CLASS, ARGS...> makeWeakCallback(const shared_ptr<CLASS>& object, void (CLASS::*mem_func)(ARGS...)) { return WeakCallback<CLASS, ARGS...>(object, mem_func); } // 測試程式碼 struct Foo { public: Foo(int num) : num_(num) {} void printAdd(int a) { std::cout << "==printAdd: " << (num_ + a) << std::endl; } private: int num_; }; int main() { shared_ptr<Foo> ptr_foo(new Foo(5)); auto wcb = makeWeakCallback(ptr_foo, &Foo::printAdd); wcb(5); return 0; }

上述程式碼的最主要功能就是實現第一個回撥物件與物件成員函式在呼叫時的繫結,因c++本身支援引數繫結功能,所以可以有如下實現方式:

template <typename Clz, typename... Args>
using BindedWeakCallback = function<void(Args...)>;

template<typename CLASS, typename... ARGS>
BindedWeakCallback<CLASS, ARGS...> makeWeakCallbackWithBind(const shared_ptr<CLASS>& object,
                                              void (CLASS::*mem_func)(ARGS...))
{
    return bind(mem_func, object.get(), placeholders::_1);
}

int main()
{
    shared_ptr<Foo> ptr_foo(new Foo(5));
    auto wcb = makeWeakCallbackWithBind(ptr_foo, &Foo::printAdd);
    wcb(5);

    return 0;
}