C++字符串键映射特定对象类方法调用的实现与修复
问题根因
你的代码编译失败的核心原因是C++非静态成员函数无法直接作为独立可调用对象使用:非静态成员函数隐式要求第一个参数是指向类实例的this指针,你直接写my_object.method_one既不是合法的函数指针,也没有完成对象实例和成员方法的绑定,无法直接存入签名为std::function<void(const std::string&)>的映射表中。
除此之外你的代码还有3个容易触发运行时错误的逻辑漏洞:
- 文件读取循环写法错误:先判断流状态再
getline会在文件末尾多处理一次无效空行 - 空行/注释行判断存在越界风险:如果读到空行,
command是空字符串,直接访问command[0]会触发内存越界 - 命令查找无校验:直接用下标访问map时,如果输入的命令不存在,会自动插入一个空的
std::function实例,调用时直接触发程序崩溃
修复实现
通过lambda捕获目标对象实例,把成员方法调用包装成和std::function签名匹配的可调用对象即可,同时修复上述逻辑漏洞,修正后的代码如下:
#include <map> #include <functional> #include <fstream> #include <sstream> #include <string> // 假设Class_Name的三个方法签名均为 void method_x(const std::string&) void read_input(std::string& input_filename, Class_Name& my_object) { // 用lambda捕获对象实例,包装成员调用 std::map<const std::string, std::function<void(const std::string&)>> argument_map = { {"input_one", [&my_object](const std::string& arg) { my_object.method_one(arg); }}, {"input_two", [&my_object](const std::string& arg) { my_object.method_two(arg); }}, {"input_three", [&my_object](const std::string& arg) { my_object.method_three(arg); }} }; std::ifstream input_file(input_filename); std::string line; // 修正文件读取循环,直接以getline返回值作为判断条件 while (std::getline(input_file, line)) { std::stringstream argument_read(line); std::string command; std::string tmp; argument_read >> command; // 空行直接跳过,避免下标越界 if (command.empty()) continue; // 注释行跳过 if (command[0] == '#') continue; // 先校验命令是否存在,避免插入空function auto cmd_it = argument_map.find(command); if (cmd_it == argument_map.end()) continue; while (argument_read >> tmp) { if (tmp[0] == '#') break; cmd_it->second(tmp); } } }
如果你不想用lambda,也可以用
std::bind绑定成员函数和对象实例,写法为std::bind(&Class_Name::method_one, &my_object, std::placeholders::_1),但lambda的写法可读性更高,编译期优化效果也更好。
内容的提问来源于stack exchange,提问作者BattleWalrus
相关产品推荐
相关产品推荐

