C++中切换对象方法的惯用实现(避免冗余条件判断)
替代大量条件判断的最佳实践方案
针对你遇到的两种场景,分别可以用哈希映射表来替代冗长的if-else链,既能让代码更整洁,又能提升查找效率。
场景1:根据字符串调用成员方法(如Bar类的doSomething)
因为无法修改SomeClass,我们可以用std::unordered_map存储字符串到函数对象的映射,把每个字符串对应到调用对应成员方法的逻辑。
修改后的代码示例
#include <unordered_map> #include <functional> #include <stdexcept> struct Bar { SomeClass obj; // 映射表:字符串 -> 接收SomeClass引用并返回int的函数 std::unordered_map<std::string, std::function<int(SomeClass&)>> method_map; // 在构造函数中初始化映射关系 Bar() { method_map["a"] = [](SomeClass& o) { return o.a(); }; method_map["b"] = [](SomeClass& o) { return o.b(); }; // 新增方法时,只需在这里添加一行映射即可 } int doSomething(std::string input) { auto iter = method_map.find(input); if (iter != method_map.end()) { // 找到对应逻辑,直接调用 return iter->second(obj); } // 处理未匹配的情况,可根据需求返回默认值或抛异常 throw std::invalid_argument("Unknown method name: " + input); } };
场景2:根据字符串直接返回整数属性
如果是直接读取类/结构体的整数成员变量,可以用成员指针来实现更高效的映射(比function对象更轻量)。
代码示例
假设你有一个包含整数属性的类:
struct Foo { int x; int y; // 其他整数属性 }; // 全局或类内的映射表:字符串 -> Foo的int成员指针 std::unordered_map<std::string, int Foo::*> attr_map = { {"x", &Foo::x}, {"y", &Foo::y} }; // 获取属性的函数 int getAttribute(Foo& foo, const std::string& name) { auto iter = attr_map.find(name); if (iter != attr_map.end()) { // 通过成员指针访问属性 return foo.*(iter->second); } throw std::invalid_argument("Unknown attribute name: " + name); }
额外优化建议
- 用
std::string_view替代std::string作为查找键,减少字符串拷贝,提升性能(C++17及以上支持)。 - 如果映射表内容不会变化,可以将其声明为
static,避免每次构造对象都重复初始化。 - 未匹配的情况必须处理(返回默认值/抛异常),避免出现未定义行为。
内容的提问来源于stack exchange,提问作者NY can
相关产品推荐
相关产品推荐

