C++ std::map映射字符串到类成员函数调用报错问题排查
报错核心原因
你在映射表里存的是C++非静态类成员函数指针,不是普通全局函数指针。非静态成员函数必须绑定对应类的实例才能调用,直接按普通函数的写法find->second(参数)调用必然触发类型错误。另外你现有代码里还有几处拼写、作用域的低级错误,一并修复即可。
最小修改方案(适配你当前无参函数的逻辑)
- 修正成员函数指针的调用语法:成员函数指针需要通过
->*(针对实例指针)或.*(针对实例本身)运算符绑定当前类的this指针才能调用,另外你当前存的函数都是无参的,不需要传type参数,把错误的调用行改成:(this->*(find->second))(); - 修正代码里的其他显性错误:
- 头文件声明的函数名和cpp实现不匹配:头文件写的
printInfopHi、prinInfoBye和cpp里的printInfoHi、printInfoBye拼写不一致,会触发链接错误,统一命名即可 - cpp里三个print函数的实现漏了
test::类作用域修饰,目前写的是全局函数,不是test类的成员,要改成void test::printInfoHello()、void test::printInfoHi()、void test::printInfoBye()的形式 - 打印调试信息的cout语句漏了流运算符:
std::cout << "Is it taking the right type: " << type << std::endl;
- 头文件声明的函数名和cpp实现不匹配:头文件写的
支持多参数扩展的长期方案
你后续要给处理函数传vector、字符串参数的话,不要直接用裸成员函数指针存储,用你已经引入的<functional>头文件中的std::function配合lambda表达式做绑定,统一所有处理函数的签名,扩展性和可维护性好很多,也不用记复杂的成员函数指针调用语法。
推荐统一约定所有命令处理函数都接收拆分后的完整参数列表(即你split得到的vector),需要什么参数直接从vector里取即可,参考实现如下:
头文件修改
#include <iostream> #include <vector> #include <map> #include <functional> #include <string> class test { private: // 统一处理函数签名:传入拆分后的参数vector void printInfoHello(const std::vector<std::string>& args); void printInfoHi(const std::vector<std::string>& args); void printInfoBye(const std::vector<std::string>& args); // 后续新增需要参数的处理函数也遵循同样签名 void printCustomMsg(const std::vector<std::string>& args); // 映射表存储统一类型的function对象 std::map<std::string, std::function<void(const std::vector<std::string>&)>> infoMap; public: test(); // 用构造函数初始化映射表,比成员直接初始化更易维护 void processInput(std::string &input); };
cpp实现修改
// 构造函数中初始化命令映射 test::test() { infoMap = { {"hello", [this](const std::vector<std::string>& args) { printInfoHello(args); }}, {"hi", [this](const std::vector<std::string>& args) { printInfoHi(args); }}, {"bye", [this](const std::vector<std::string>& args) { printInfoBye(args); }}, // 新增命令直接追加即可,lambda内部可以灵活适配逻辑 {"say", [this](const std::vector<std::string>& args) { printCustomMsg(args); }} }; } void test::processInput(std::string &input) { std::vector<std::string> val = explodeVals::split(input, ' '); if (val.empty()) { std::cout << "Empty input!" << std::endl; return; } std::string type = val[0]; std::cout << "Is it taking the right type: " << type << std::endl; auto find = infoMap.find(type); if (find == infoMap.end()) { std::cout << "Error, input not found" << std::endl; return; } // 直接调用即可,不需要处理复杂的成员指针语法 find->second(val); } // 所有成员函数实现加类作用域修饰 void test::printInfoHello(const std::vector<std::string>& args){ std::cout << "Saying hello!" << std::endl; } void test::printInfoHi(const std::vector<std::string>& args){ std::cout << "Saying hi!" << std::endl; } void test::printInfoBye(const std::vector<std::string>& args){ std::cout << "Saying good bye!" << std::endl; } // 需要参数的函数直接从传入的args里取值即可 void test::printCustomMsg(const std::vector<std::string>& args){ if (args.size() >= 2) { std::cout << "Custom message: " << args[1] << std::endl; } }
内容的提问来源于stack exchange,提问作者noClueAboutWhatIMDoing
相关产品推荐
相关产品推荐

