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

C++成员函数指针调用报错:无法调用存储对象的存储成员函数

事件系统成员函数指针调用问题解决

问题重现

尝试实现一个事件系统,让event_triggerer存储event_receiver的成员函数指针并调用,但代码出现编译错误:

原代码:

typedef void(event_receiver::* ev_rec_func)(const event_receiver::Msg&);

class event_receiver {
public:
    struct Msg {
        int irrelevant_test_data;
    };
    virtual void event_callback0(const Msg& m) {};
};

class event_triggerer {
private:
    std::vector<std::pair<event_receiver*, ev_rec_func>> suscribers_vec;
public:
void trigger_event(const event_receiver::Msg& m) {
    for (std::pair<event_receiver*, ev_rec_func>& e : suscribers_vec) {
        // 错误:expression must have pointer to member type
        e.first->*(e.second(m));
    }
}
};

遇到的错误:

原调用语句报错:expression must have pointer to member type
修改为(e.first->*e.second)(m);后报错:a pointer to a bound function may only be used to call the function
VS中hoverev_rec_func时显示:typedef void ev_rec_func(const &),类型显示异常

错误原因分析

  1. typedef位置错误:原代码中typedef写在event_receiver类定义之前,此时编译器还未解析event_receiver类及其内部的Msg结构体,导致ev_rec_func的类型无法被正确解析,这是VS显示异常类型的根本原因,也会引发后续调用错误。
  2. 成员函数指针调用语法错误:原调用语句e.first->*(e.second(m))逻辑错误,试图直接调用成员函数指针e.second(成员函数指针必须绑定对象才能调用),然后将结果用于->*操作,完全不符合成员函数指针的调用规则。

修复方案

步骤1:调整typedef位置

将typedef移至event_receiver类定义之后,确保编译器能识别event_receiver和Msg类型:

class event_receiver {
public:
    struct Msg {
        int irrelevant_test_data;
    };
    virtual void event_callback0(const Msg& m) {};
};

// 现在可以正确解析event_receiver::Msg类型
typedef void(event_receiver::* ev_rec_func)(const event_receiver::Msg&);

步骤2:修正成员函数指针调用语法

正确的成员函数指针调用格式是(对象指针->*成员函数指针)(参数),需要用括号确保优先级:

void trigger_event(const event_receiver::Msg& m) {
    for (auto& e : suscribers_vec) {
        // 正确调用方式:先绑定对象和成员函数指针,再传参调用
        (e.first->*e.second)(m);
    }
}

完整可编译代码

#include <vector>
#include <utility>

class event_receiver {
public:
    struct Msg {
        int irrelevant_test_data;
    };
    virtual void event_callback0(const Msg& m) {};
};

typedef void(event_receiver::* ev_rec_func)(const event_receiver::Msg&);

class event_triggerer {
private:
    std::vector<std::pair<event_receiver*, ev_rec_func>> suscribers_vec;
public:
    void trigger_event(const event_receiver::Msg& m) {
        for (auto& e : suscribers_vec) {
            (e.first->*e.second)(m);
        }
    }

    // 新增订阅函数用于测试
    void subscribe(event_receiver* receiver, ev_rec_func func) {
        suscribers_vec.emplace_back(receiver, func);
    }
};

// 测试示例
int main() {
    event_receiver recv;
    event_triggerer trigger;
    trigger.subscribe(&recv, &event_receiver::event_callback0);
    event_receiver::Msg msg{};
    trigger.trigger_event(msg);
    return 0;
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.14 01:37:03