程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> C語言 >> C++ >> 關於C++ >> C++11新特性之 CALLBACKS

C++11新特性之 CALLBACKS

編輯:關於C++

《C++11新特性之std::function》提到了std::function作為回調函數。

今天主要討論不同情況下std::function作為回調使用。

使用回調

#include 
#include 
namespace {
using cb1_t = std::function;
using cb2_t = std::function;

void foo1()
{
    std::cout << foo1 is called
;
}

void foo2(int i)
{
    std::cout << foo2 is called with:  << i << 
;
}

struct S {
    void foo3()
    {
        std::cout << foo3 is called.
;
    }
};

}

int main()
{
    // Bind a free function.
    cb1_t f1 = std::bind(&foo1);
    // Invoke the function foo1.
    f1();

    // Bind a free function with an int argument.
    // Note that the argument can be specified with bind directly.
    cb1_t f2 = std::bind(&foo2, 5);
    // Invoke the function foo2.
    f2();

    // Bind a function with a placeholder.
    cb2_t f3 = std::bind(&foo2, std::placeholders::_1);
    // Invoke the function with an argument.
    f3(42);

    // Bind a member function.
    S s;
    cb1_t   f4 = std::bind(&S::foo3, &s);
    // Invoke the method foo3.
    f4();

    // Bind a lambda.
    cb1_t f5 = std::bind([] { std::cout << lambda is called
; });
    f5();

    return 0;
}

存儲回調
使用回調是非常好的,但是更多的情況下,我們往往需要存儲一些回調函數,並稍後使用。例如,注冊一個客戶端到某個事件上。(也許注冊和事件是C Sharp的詞匯)

我們經常使用std::vector來完成任務。
缺點就是,我們不能再vector中存儲不同的類型 。
但是,大多數情況下,一種類型就可以滿足我們了。

#include 
#include 
#include 

namespace {

using cb1_t = std::function;
using callbacks_t = std::vector;

callbacks_t callbacks;

void foo1()
{
    std::cout << foo1 is called
;
}

void foo2(int i)
{
    std::cout << foo2 is called with:  << i << 
;
}

} // end anonymous namespace

int main()
{
    // Bind a free function.
    cb1_t f1 = std::bind(&foo1);
    callbacks.push_back(f1);

    // Bind a free function with an int argument.
    // Here the argument is statically known.
    cb1_t f2 = std::bind(&foo2, 5);
    callbacks.push_back(f2);

    // Bind a free function with an int argument.
    // Here the argument is bound and can be changed at runtime.
    int n = 15;
    cb1_t f3 = std::bind(&foo2, std::cref(n));
    callbacks.push_back(f3);

    // Invoke the functions
    for(auto& fun : callbacks) {
        fun();
    }
    return 0;
}

包裝函數
上面提到都不是重點,個人覺得特別重要的就是std::function作為函數的參數使用。
下面一個例子就將展示一個函數被copy不同的參數。

Note that we always produce an std::function, even though in some cases we could invoke the target directly. Whether this is required depends on the use case. If all the function does is invoking the target, then directly doing it is more efficient. The reason is that std::function does have some overhead, because it is a polymorphic class.

#include 
#include 

namespace {

using cb1_t = std::function;
using cb2_t = std::function;

// Wrapper function with std::function without arguments.
template
void call(std::function f)
{
    f();
}

// Wrapper function with std::function with arguments.
template
void call(std::function f, A... args)
{
    f(args...);
}

// Wrapper function for generic callable object without arguments.
// Delegates to the std::function call.
template
void call(R f(void))
{
    call(std::function(f));
}

// Wrapper function for generic callable object with arguments.
// Delegates to the std::function call.
template
void call(R f(A...), A... args)
{
    call(std::function(f), args...);
}

// Wrapper for a function pointer (e.g. a lambda without capture) without
// arguments.
using fp = void (*)(void);
void call(fp f)
{
    call(std::function(f));
}

void foo1()
{
    std::cout << foo1 is called
;
}

void foo2(int i)
{
    std::cout << foo2 is called with:  << i << 
;
}

} // end anonymous namespace

int main()
{
    // Call function 1.
    call(&foo1);

    // Alternative to call function 1.
    cb1_t f1 = std::bind(&foo1);
    call(f1);

    // Call function 2.
    call(&foo2, 5);

    // Alternative to call function 2.
    cb2_t f2 = std::bind(&foo2, std::placeholders::_1);
    call(f2, 5);

    // Here is an example with a lambda. It calls the function that takes a
    // function pointer.
    call([] { std::cout << lambda called
; });

    return 0;
}

 

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved