- 什么是回调函数
- 回调函数用法
回调函数
回调函数,是计算机编程中对某一段可执行代码的引用,它被作为参数传递给另一段代码;
回调函数不是由该函数的实现方直接调用,而是在特定的事件或条件发生时由另外的一方调用的,用于对该事件或条件进行响应;
- 普通函数的回调
- 类成员函数的回调
- 基于std::function和std::bind的回调
- Lambda表达式的回调
普通函数的回调
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28
| #include <stdio.h> #include <stdlib.h> #include <string> typedef int (*callBackFunc)(char* name); int playBegin(char* name) { printf("视频开始解码,即将出现画面....\n"); return 1; } int playEnd(char* name) { printf("视频播放结束....\n"); return 1; } int play(callBackFunc fn, char* name) { return (*fn)(name); } int main() { char pName[1024] = "色即是空"; play(playBegin,pName); play(playEnd,pName); return 0; }
|
- playBegin(),playEnd()是普通函数,定义了回调函数的逻辑;
- play()函数是一个高阶函数,接收函数指针作为参数,并在内部调用回调函数;
- 在main()中,将函数playBegin(),playEnd()的地址传递给play()实现回调;
需要注意的是:
在 play
函数中,fn
是一个 callBackFunc
类型的参数,即它是一个指向函数的指针。因此,(*fn)(name)
和 fn(name)
都是合法的函数调用方式,它们都表示通过函数指针 fn
调用指向的函数,并传递 name
作为参数。
(*fn)(name)
是显式地通过解引用函数指针来调用函数。*fn
获取函数指针指向的函数,然后调用该函数。
fn(name)
是更简洁的写法,直接通过函数指针调用函数。在 C 语言中,当函数指针用于调用函数时,可以省略解引用操作符 *
,因为上下文已经明确了这是一个函数调用操作.
类成员函数的回调
示例1
由于普通成员函数必须依赖具体对象才能调用,因此在回调时需要传递对象指针和成员函数指针。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23
| #include <iostream> using namespace std;
class CallbackHandler{ public: void memberCallback(int value){ cout << "成员函数回调,被调用时传入的值是:" << value << endl; } };
void executableMemberCallback(CallbackHandler* obj, void (CallbackHandler::*callback)(int), int value){ (obj->*callback)(value); }
int main(){ CallbackHandler handler; executableMemberCallback(&handler, &CallbackHandler::memberCallback, 42); return 0; }
|
- CallbackHandler类中定义了一个成员函数memberCallback;
- executeMemberCallback接收对象指针CallbackHandler* obj和成员函数指针void (CallbackHandler::*callback)(int)
- 通过(obj->*callback)(value)调用成员函数;
- 在main函数中,通过对象handler和成员函数指针&CallbackHandler::memberCallback实现回调;
示例2
在c++面向对象里面,回调函数是成员函数的情况更常见,这样的好处是,一个类A的一个函数生成一个结果之后,可以调用另一个类B的成员函数。而不必类A拥有B的实例。
尤其是在B中有了A的实例的情况下,A中如果再包含B的实例会出现循环引用的问题 ,这也是可以解决的,但是这种耦合还是容易让逻辑变得混乱。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29
| typedef std::function<void (string)> CaptureCallback;
class CaptureController{ public: CaptureCallback callback; CaptureController(CaptureCallback callback):callback(callback){}; void capturePic(CaptureCallback callback){ string t = "a pic"; callback(t); } }
class UI{ void startCapture(){ CaptureController c(std::bind(&UI::renderPic,this,_1)); c.capturePic(); } void renderPic(string t){ print(t); } }
UI ui; ui.startCapture();
|
std::function/std::bind
- std::function可以存储任意可调用对象(普通函数,成员函数,Lambda表达式)
- std::bind可以绑定成员函数和对象
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36
| #include <iostream> #include <functional> using namespace std;
typedef function<void(int)> CallBackFunc;
void executeCallback(CallBackFunc callback, int value){ callback(value); }
void freeFunction(int value){ cout << "普通函数回调,传入的参数为:" << value << endl; }
class CallbackHandler{ public: void memberCallback(int value){ cout << "成员函数回调,传入的参数为:" << value << endl; } };
int main(){ CallbackHandler handler; executeCallback(freeFunction, 42);
executeCallback([](int value){ cout << "Lambda 回调,传入的参数为:" << value << endl; }, 43);
executeCallback(std::bind(&CallbackHandler::memberCallback, &handler, std::placeholders::_1), 44);
return 0; }
|
function<void(int)>
可以存储普通函数,Lambda表达式或绑定后的成员函数;
- 使用std::bind将成员函数和对象绑定,并通过std::placeholder::_1占位符传递参数;