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

如何将调用者对象作为参数传入回调函数并访问类成员

问题分析与解决

你遇到的error: invalid use of void expression错误,核心原因是test.onEvent(onUpdateEvent(test))这行代码直接调用了onUpdateEvent函数(返回void),但onEvent需要接收的是std::function<void(Test)>类型的对象,不是void值。另外原代码里的回调参数类型也存在不匹配:onUpdateEvent接收的是Test&引用,但std::function定义的是传值的Test,需要统一类型。

下面提供几种不需要全局变量的解决方案:

方案1:使用Lambda表达式包装回调

这是最简洁直观的方式,直接在注册回调时用lambda把目标函数包装成符合std::function要求的类型,同时在Update方法里传入*this(注意要调整std::function的参数为引用,避免不必要的对象拷贝)。

修改后的完整代码:

#include <iostream>
#include <functional>
#include <thread>
#include <chrono>

class Test
{
public:
    int x = 0; // 初始化x,避免未定义行为
    void onEvent(const std::function<void(Test&)> &callback)
    {
        Test_Callback = callback;
    };

    std::function<void(Test&)> Test_Callback;     

    void Update()
    {
        x += 1;
        if (Test_Callback)
        {
            Test_Callback(*this); // 传入当前对象的引用
        }
    }
};

void onUpdateEvent(Test& t)
{
    printf("update %d\n", t.x);
}

int main()
{
    Test test;
    // 用lambda包装onUpdateEvent,生成符合要求的function对象
    test.onEvent([](Test& t) { onUpdateEvent(t); });

    while (1)
    {
        test.Update();
        // 加延迟避免输出刷屏
        std::this_thread::sleep_for(std::chrono::seconds(1));
    }

    return 0;
}

方案2:使用std::bind绑定函数

如果偏好使用std::bind,可以把onUpdateEvent包装成适配的可调用对象,不需要提前绑定具体的Test实例(因为参数会在Update时传入):

修改main函数里的注册代码即可(其余代码同方案1):

int main()
{
    Test test;
    // 用std::bind生成符合要求的function对象
    test.onEvent(std::bind(&onUpdateEvent, std::placeholders::_1));

    while (1)
    {
        test.Update();
        std::this_thread::sleep_for(std::chrono::seconds(1));
    }

    return 0;
}

方案3:将回调改为类成员函数

如果回调逻辑属于Test类的一部分,可以直接把onUpdateEvent改成Test的成员函数,这样不需要额外传参就能直接访问类成员:

修改后的代码片段:

#include <iostream>
#include <functional>
#include <thread>
#include <chrono>

class Test
{
public:
    int x = 0;
    void onEvent(const std::function<void(Test&)> &callback)
    {
        Test_Callback = callback;
    };

    std::function<void(Test&)> Test_Callback;     

    void Update()
    {
        x += 1;
        if (Test_Callback)
        {
            Test_Callback(*this);
        }
    }

    // 成员函数作为回调,直接访问类成员x
    void onUpdateEvent()
    {
        printf("update %d\n", x);
    }
};

int main()
{
    Test test;
    // 用lambda绑定成员函数
    test.onEvent([&test](Test&) { test.onUpdateEvent(); });

    while (1)
    {
        test.Update();
        std::this_thread::sleep_for(std::chrono::seconds(1));
    }

    return 0;
}

关键修改点总结

  • 将std::function<void(Test)>改为std::function<void(Test&)>,统一参数类型为引用,避免对象拷贝。
  • 注册回调时,不能直接调用函数(onUpdateEvent(test)),而是传递lambda、std::bind生成的可调用对象,确保onEvent接收符合类型要求的std::function。
  • 在Update方法里调用回调时,传入*this作为参数,让回调能访问当前对象的成员。

内容的提问来源于stack exchange,提问作者dkts2000

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.26 07:16:23