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

如何创建键为string、值为类成员函数指针的std::map

类成员函数的std::map实现方案

问题描述

原本使用全局函数时,可以直接将函数指针存入std::map实现命令映射:

void nvmRead(unsigned char* msg, unsigned char* resp_frame);
void nvmWrite(unsigned char* msg, unsigned char* resp_frame);
void nvmProvision(unsigned char* msg, unsigned char* resp_frame);
void nvmStatus(unsigned char* msg, unsigned char* resp_frame);

std::map<std::string, void (*)(unsigned char* msg, unsigned char* resp_frame)> command_table = {
  { "NVM_READ", nvmRead },
  { "NVM_WRITE", nvmWrite },
  { "NVM_PROVISION", nvmProvision },
  { "NVM_STATUS", nvmStatus }
};

调用时直接通过command_table.at(s)(parm1, parm2);即可。但将这些函数移到类内部后,出现类型转换错误:

error: could not convert '{{"NVM_READ", ((myns::RaidDevCommInTask*)this)->myns::RaidDevCommInTask::nvmRead}, {"NVM_WRITE", ((myns::RaidDevCommInTask*)this)->myns::RaidDevCommInTask::nvmWrite}, {"NVM_PROVISION", ((myns::RaidDevCommInTask*)this)->myns::RaidDevCommInTask::nvmProvision}, {"NVM_STATUS", ((myna::RaidDevCommInTask*)this)->myns::RaidDevCommInTask::nvmStatus}}' from '<brace-enclosed initializer list>' to 'std::map<std::__cxx11::basic_string<char>, void (*)(unsigned char*, unsigned char*)>'
   85 |   };

构造函数中赋值同样报错:

src/tests/raid_dev_comm_in_task.cpp:40:31: error: cannot convert 'myns::RaidDevCommInTask::nvmRead' from type 'void (myns::RaidDevCommInTask::)(unsigned char*, unsigned char*)' to type 'std::map<std::__cxx11::basic_string<char>, void (*)(unsigned char*, unsigned char*)>::mapped_type' {aka 'void (*)(unsigned char*, unsigned char*)'}
   40 |   command_table["NVM_READ"] = nvmRead;
      |                               ^~~~~~~

核心原因

类成员函数指针与普通全局函数指针类型不兼容:成员函数隐含了一个this指针作为第一个参数,因此它的类型是void (类名::*)(参数列表),无法直接转换为普通函数指针void (*)(参数列表)。

解决方案

方案1:使用成员函数指针作为map值类型

直接定义成员函数指针类型的map,调用时需要通过对象实例(如this)来调用成员函数指针。

#include <map>
#include <string>

namespace myns {
class RaidDevCommInTask {
private:
    void nvmRead(unsigned char* msg, unsigned char* resp_frame) {
        // 实现逻辑,可访问类私有成员
    }
    void nvmWrite(unsigned char* msg, unsigned char* resp_frame) {
        // 实现逻辑
    }
    void nvmProvision(unsigned char* msg, unsigned char* resp_frame) {
        // 实现逻辑
    }
    void nvmStatus(unsigned char* msg, unsigned char* resp_frame) {
        // 实现逻辑
    }

    // 定义成员函数指针的别名,简化类型书写
    using CommandFunc = void (RaidDevCommInTask::*)(unsigned char*, unsigned char*);
    std::map<std::string, CommandFunc> command_table = {
        {"NVM_READ", &RaidDevCommInTask::nvmRead},
        {"NVM_WRITE", &RaidDevCommInTask::nvmWrite},
        {"NVM_PROVISION", &RaidDevCommInTask::nvmProvision},
        {"NVM_STATUS", &RaidDevCommInTask::nvmStatus}
    };

public:
    void executeCommand(const std::string& cmd, unsigned char* msg, unsigned char* resp) {
        auto iter = command_table.find(cmd);
        if (iter != command_table.end()) {
            // 必须通过对象实例调用成员函数指针,语法为:(对象->*成员指针)(参数)
            (this->*(iter->second))(msg, resp);
        }
    }
};
} // namespace myns

方案2:使用std::function + std::bind绑定this

将成员函数与当前对象的this绑定,封装成std::function类型,调用方式更接近原全局函数的用法。

#include <map>
#include <string>
#include <functional>

namespace myns {
class RaidDevCommInTask {
private:
    void nvmRead(unsigned char* msg, unsigned char* resp_frame) {
        // 实现逻辑
    }
    void nvmWrite(unsigned char* msg, unsigned char* resp_frame) {
        // 实现逻辑
    }
    void nvmProvision(unsigned char* msg, unsigned char* resp_frame) {
        // 实现逻辑
    }
    void nvmStatus(unsigned char* msg, unsigned char* resp_frame) {
        // 实现逻辑
    }

    std::map<std::string, std::function<void(unsigned char*, unsigned char*)>> command_table;

public:
    RaidDevCommInTask() {
        // 用std::bind绑定this和成员函数,占位符表示后续传入的参数
        command_table["NVM_READ"] = std::bind(&RaidDevCommInTask::nvmRead, this, std::placeholders::_1, std::placeholders::_2);
        command_table["NVM_WRITE"] = std::bind(&RaidDevCommInTask::nvmWrite, this, std::placeholders::_1, std::placeholders::_2);
        command_table["NVM_PROVISION"] = std::bind(&RaidDevCommInTask::nvmProvision, this, std::placeholders::_1, std::placeholders::_2);
        command_table["NVM_STATUS"] = std::bind(&RaidDevCommInTask::nvmStatus, this, std::placeholders::_1, std::placeholders::_2);
    }

    void executeCommand(const std::string& cmd, unsigned char* msg, unsigned char* resp) {
        auto iter = command_table.find(cmd);
        if (iter != command_table.end()) {
            // 直接调用,无需手动处理this
            iter->second(msg, resp);
        }
    }
};
} // namespace myns

方案3:使用Lambda捕获this(C++11及以上)

用Lambda表达式捕获当前对象的this,直接在Lambda内部调用成员函数,写法更简洁直观。

#include <map>
#include <string>
#include <functional>

namespace myns {
class RaidDevCommInTask {
private:
    void nvmRead(unsigned char* msg, unsigned char* resp_frame) {
        // 实现逻辑
    }
    void nvmWrite(unsigned char* msg, unsigned char* resp_frame) {
        // 实现逻辑
    }
    void nvmProvision(unsigned char* msg, unsigned char* resp_frame) {
        // 实现逻辑
    }
    void nvmStatus(unsigned char* msg, unsigned char* resp_frame) {
        // 实现逻辑
    }

    std::map<std::string, std::function<void(unsigned char*, unsigned char*)>> command_table;

public:
    RaidDevCommInTask() {
        // Lambda捕获this,直接调用成员函数
        command_table["NVM_READ"] = [this](unsigned char* msg, unsigned char* resp) {
            this->nvmRead(msg, resp);
        };
        command_table["NVM_WRITE"] = [this](unsigned char* msg, unsigned char* resp) {
            this->nvmWrite(msg, resp);
        };
        command_table["NVM_PROVISION"] = [this](unsigned char* msg, unsigned char* resp) {
            this->nvmProvision(msg, resp);
        };
        command_table["NVM_STATUS"] = [this](unsigned char* msg, unsigned char* resp) {
            this->nvmStatus(msg, resp);
        };
    }

    void executeCommand(const std::string& cmd, unsigned char* msg, unsigned char* resp) {
        auto iter = command_table.find(cmd);
        if (iter != command_table.end()) {
            iter->second(msg, resp);
        }
    }
};
} // namespace myns

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.18 11:05:42