You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何声明可适配任意参数的函数指针变量实现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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.06 22:20:27