如何声明可适配任意参数的函数指针变量实现Dialog回调?
实现支持任意参数回调的Dialog处理器
你需要为Dialog类实现支持不同参数或无参的“是/否”回调,原固定函数指针无法适配带参数的情况,这里提供两种可行方案:
方案1:用std::function<void()>统一回调类型
因为Dialog的调用逻辑是无参执行method_yes(),所以可以把带参数的逻辑通过绑定参数或捕获变量的方式,转换成无参的可调用对象,用std::function<void()>来存储回调。
首先修改Dialog类的成员(需要包含<functional>头文件):
#include <functional> #include <string> class Dialog { protected: Dialog() { } static Dialog* singleton; public: Dialog(Dialog &other) = delete; void operator=(const Dialog &) = delete; static Dialog *instance(); std::string question; std::function<void()> method_yes; std::function<void()> method_no; static bool has_dialog(); static void clear(); }; // 原静态成员和方法实现不变 Dialog* Dialog::singleton = nullptr; Dialog* Dialog::instance() { if (singleton == nullptr) { singleton = new Dialog(); } return singleton; } bool Dialog::has_dialog() { return singleton != nullptr; } void Dialog::clear() { if (singleton) { delete singleton; singleton = nullptr; } }
无参回调使用
直接赋值无参lambda即可:
auto yes = []() { ExitProcess(0); }; Dialog::instance()->question = "Do you want to exit?"; Dialog::instance()->method_yes = yes;
带参数回调使用
通过lambda捕获参数或std::bind固化参数,把带参逻辑转换成无参回调:
// 方式1:lambda捕获参数 int exit_code = 1; auto yes = [exit_code]() { ExitProcess(exit_code); }; Dialog::instance()->method_yes = yes; // 方式2:std::bind绑定参数 #include <functional> auto yes = std::bind(ExitProcess, 1); Dialog::instance()->method_yes = yes;
调用时依然保持原逻辑:
if (Dialog::has_dialog()) { // 渲染问题和按钮逻辑 // 点击“是”时调用 Dialog::instance()->method_yes(); Dialog::clear(); }
方案2:模板化Dialog类(适配不同回调签名)
如果需要在调用回调时才传入参数,可以把Dialog做成模板类,根据回调签名实例化:
#include <functional> #include <string> template<typename YesFunc = std::function<void()>, typename NoFunc = std::function<void()>> class Dialog { protected: Dialog() {} static Dialog* singleton; public: Dialog(const Dialog&) = delete; void operator=(const Dialog&) = delete; static Dialog* instance() { if (!singleton) singleton = new Dialog(); return singleton; } std::string question; YesFunc method_yes; NoFunc method_no; static bool has_dialog() { return singleton != nullptr; } static void clear() { if (singleton) { delete singleton; singleton = nullptr; } } }; // 初始化静态模板成员 template<typename Y, typename N> Dialog<Y, N>* Dialog<Y, N>::singleton = nullptr;
带参数回调使用示例
// 实例化带int参数的Dialog using ExitDialog = Dialog<std::function<void(int)>>; ExitDialog::instance()->question = "Exit with code?"; ExitDialog::instance()->method_yes = [](int code) { ExitProcess(code); }; // 调用时传入参数 if (ExitDialog::has_dialog()) { // 渲染逻辑 ExitDialog::instance()->method_yes(1); ExitDialog::clear(); }
这种方式的缺点是不同回调签名对应不同的Dialog实例类型,不如方案1的调用逻辑统一。
内容的提问来源于stack exchange,提问作者elllkere
相关产品推荐
相关产品推荐

