如何定义Lambda函数以捕获类的this指针?
问题:带捕获的Lambda无法转换为函数指针作为日期变化回调
我有一个用于跟踪时间的TimeSystem类,允许其他类在日期变化时注册回调函数。现有可正常运行的代码片段如下:
#define MAX_CB_CHANGE_FUNCTIONS 50 typedef void (*dayChangeFunc)(int prevDay,int nowDay); class TimeSystem { private: // 存储函数指针的数组 dayChangeFunc dayChangeFunctions[MAX_CB_CHANGE_FUNCTIONS]; // 日期变化时触发的函数 void emitDayChange(int prev, int now); public: void regDayChange(dayChangeFunc); }; /* * 注册日期变化回调函数 * 最大函数指针数量为MAX_CB_CHANGE_FUNCTIONS(详见timeSys.h) */ void TimeSystem::regDayChange(void (*dayChangeFunc)(int prevDay,int nowDay)){ if( currDayCbIndex >= MAX_CB_CHANGE_FUNCTIONS ){ if(isDebugOn){ debug.print(DEBUG_WARN,"[Time_sys] - Can not register an other day change function.\n"); return; } } dayChangeFunctions[currDayCbIndex] = dayChangeFunc; currDayCbIndex++; } /* * 向所有已注册函数触发日期变化事件 */ void TimeSystem::emitDayChange(int prev, int now){ // 初始化时不触发 if( prev == 0 ){ return; } for (size_t i = 0; i < MAX_CB_CHANGE_FUNCTIONS; i++){ if(dayChangeFunctions[i]){ dayChangeFunctions[i](prev,now); } } }
其他类原本可以通过无捕获的Lambda使用该功能:
timeSys.regDayChange([](int prevDay,int nowDay){ Serial.printf("Day changed from prev: %d to now: %d\n",prevDay,nowDay); });
当尝试在Lambda中捕获this指针以调用类内部函数时:
timeSys.regDayChange([this](int prevDay,int nowDay){ callSomeInternalFunction(); });
出现编译错误:
no suitable conversion function from "lambda [](int prevDay, int nowDay)->void" to "dayChangeFunc"
解决方案
问题根源是带有捕获的Lambda无法隐式转换为普通函数指针,需要改用std::function来存储回调。具体修改如下:
- 修改回调类型定义
将原有的函数指针类型替换为std::function:
using dayChangeFunc = std::function<void(int, int)>;
- 更新注册函数的声明
在TimeSystem类的public接口中修改注册函数:
void regDayChange(dayChangeFunc cb);
- 改写注册函数的实现
/* * 注册日期变化回调函数 * 最大函数指针数量为MAX_CB_CHANGE_FUNCTIONS(详见timeSys.h) */ void TimeSystem::regDayChange( dayChangeFunc cb ){ if( currDayCbIndex >= MAX_CB_CHANGE_FUNCTIONS ){ if(isDebugOn){ debug.print(DEBUG_WARN,"[Time_sys] - Can not register an other day change function.\n"); return; } } dayChangeFunctions[currDayCbIndex] = cb; currDayCbIndex++; }
修改完成后,即可在类中使用带this捕获的Lambda注册回调:
class SampleClass { private: int exampleCounter = 0; public: void init(){ TimeSystem timeSys; timeSys.regDayChange([this](int prevDay,int nowDay){ Serial.printf("Day changed from prev: %d to now: %d\n",prevDay,nowDay); exampleCounter++; }); } };
内容的提问来源于stack exchange,提问作者Dr.Random
相关产品推荐
相关产品推荐

