如何使用 std::function 撰寫 Callback Function?

前言

std::function 是 c++11 後的新功能,定義於 header <functional> 中。有點像是 c 語言中的 function pointer,除此之外,也有更廣泛的應用,任何 CopyConstructableCallable 物件皆可以 std::function 儲存、複製以及調用。

舉例來說,function, lambda expression, bind expression 是這類型的物件,另外,像是成員函數 (member function) 、資料成員 (member data) 的指標,也是 std::function 的範疇。

其中儲存的可呼叫的物件即是 std::function 的目標 (target)。假如今天我們沒有給定任何目標,則此種情形稱作 empty,並且會丟出 std::bad_function_call 的 exception。

而 callback function 中文通常翻譯成回調函式或回呼函式,是指一個能藉由參數傳遞通往另外一個函式的函式。

方法

首先,我們先來看 std::function 的定義

1template<class R, class... args>
2class function<R(args)>

由此可見,如果要使用 function 這個類別,在初始化時我們要先定義傳入的類別型態 args 與傳出的類別型態 R。這兩個參數對應了 Callable 物件中的參數與回傳型態,如果沒有回傳值或傳入值,則以 void 表示。以下是一個簡單的例子,

1std::function<void(int, float)> callback;

我們定義了一個實例了一個名叫 callback 的 std::function,在這個 std::function 中,傳入的參數分別是型態為 intfloat 的兩個參數,因為沒有回傳值,所以將 R 設為 void

實例化此 std::function 後,我們需要將實際被呼叫的函式存入其中。std::function 中覆寫了等號的運算子 operator= 作為賦予新目標的方法。也就是如果我們今天我們今天有一個函式叫做 func,其傳入的兩個參數分別是 intfloat,我們可以直接以等號賦值。

1void func(int a, float b);
2callback = func;

範例程式

 1#include <iostream>
 2#include <functional>
 3
 4std::function<void(int, float)> callback;
 5
 6void add(int a, float b)
 7{
 8  	std::cout << a + b << std::endl;
 9}
10
11void sub(int a, float b)
12{
13	  std::cout << a - b << std::endl;
14}
15
16void func(int a, float b, std::function<void(int, float)> c)
17{
18	  c(a, b);
19}
20
21int main()
22{
23	  int a = 5;
24  	float b = 0.3
25
26    // 5 + 0.3
27    callback = add;
28 		func(a, b, callback);
29  
30    // 5 - 0.3
31    callback = sub;
32    func(a, b, callback);
33}