回撥函式(callback function)是指作為引數傳遞給另一個函式的函式,在某個事件發生或某個任務完成時被呼叫。回撥函式在非同步程式設計中非常常見,因為它們允許程式碼在某個操作完成後自動執行某些行為,而無需阻塞程式。
回撥函式的基本特徵
- 作為引數傳遞:回撥函式通常是作為引數傳遞給另一個函式。
- 由呼叫者決定何時執行:回撥函式不會立即執行,而是由接受它的函式在適當的時候呼叫。
- 非同步程式設計的核心:在處理非同步操作時,例如網路請求、事件監聽或定時任務,回撥函式可以讓程式繼續執行其他程式碼,而不必等待某個操作完成。
在C++中,回撥函式通常是透過函式指標、std::function
或者基於類的回撥機制來實現的。以下是使用函式指標和std::function
來實現回撥函式的兩個簡單例子。
1. 使用函式指標實現回撥函式
示例
#include <iostream>
// 定義一個函式,它接受一個回撥函式作為引數
void process(int x, void (*callback)(int)) {
std::cout << "Processing number: " << x << std::endl;
callback(x); // 呼叫回撥函式
}
// 定義一個回撥函式
void printResult(int result) {
std::cout << "Callback called with result: " << result << std::endl;
}
int main() {
process(10, printResult); // 將回撥函式傳遞給process函式
return 0;
}
解釋:
process
函式接受兩個引數:一個整數和一個回撥函式。回撥函式的型別是void (*callback)(int)
,表示它是一個返回型別為void
,引數為int
的函式指標。printResult
是回撥函式,當process
函式完成它的主要任務後,它會呼叫printResult
。
輸出:
Processing number: 10
Callback called with result: 10
2. 使用 std::function
實現回撥函式
C++11引入了 std::function
,它更加靈活,可以接受函式指標、lambda表示式、或者類的成員函式作為回撥函式。
示例
#include <iostream>
#include <functional>
// 定義一個函式,它接受一個std::function作為回撥函式
void process(int x, const std::function<void(int)>& callback) {
std::cout << "Processing number: " << x << std::endl;
callback(x); // 呼叫回撥函式
}
// 定義一個回撥函式
void printResult(int result) {
std::cout << "Callback called with result: " << result << std::endl;
}
int main() {
// 使用函式指標
process(10, printResult);
// 使用lambda表示式作為回撥
process(20, [](int result) {
std::cout << "Lambda called with result: " << result << std::endl;
});
return 0;
}
解釋:
process
函式現在接受一個std::function<void(int)>
型別的回撥函式。這種方式比直接使用函式指標更加靈活。- 我們可以使用標準函式
printResult
作為回撥,也可以使用lambda表示式(匿名函式)作為回撥。
輸出:
Processing number: 10
Callback called with result: 10
Processing number: 20
Lambda called with result: 20
3. 使用類成員函式作為回撥
如果我們需要一個類的成員函式作為回撥,我們可以結合 std::function
和 std::bind
或者直接使用 lambda 表示式。
示例
#include <iostream>
#include <functional>
#include <string>
class Processor {
public:
void process(int x, const std::function<void(int)>& callback) {
std::cout << "Processing number: " << x << std::endl;
callback(x);
}
void memberCallback(int result) {
std::cout << "Member callback called with result: " << result << std::endl;
}
};
int main() {
Processor p;
// 使用類的成員函式作為回撥
p.process(30, std::bind(&Processor::memberCallback, &p, std::placeholders::_1));
// 或者直接使用lambda表示式
p.process(40, [&](int result) {
p.memberCallback(result);
});
return 0;
}
解釋:
std::bind
用於將類成員函式和具體物件繫結,這樣我們可以將成員函式作為回撥傳遞。std::placeholders::_1
表示佔位符,用於傳遞給回撥函式的引數。- 我們也可以直接使用 lambda 表示式來呼叫類的成員函式。
輸出:
Processing number: 30
Member callback called with result: 30
Processing number: 40
Member callback called with result: 40
總結
在C++中實現回撥函式有多種方式:
- 函式指標:最基礎的實現方式。
std::function
:從C++11開始的更靈活的回撥機制,支援lambda、函式指標、類成員函式等。- 類的成員函式:透過
std::bind
或 lambda 方式實現類的回撥函式。
std::function
和lambda表示式更加靈活和現代化,適用於更多複雜的回撥場景。