枚举类到函数重载的映射问题求助
枚举类到函数重载的映射问题求助
嗨,我太懂你这种重复代码堆起来、维护时要改好几处的痛苦了!咱们先把你的问题再明确下:你有个类,里面有一堆同模式的成员函数(比如memfunc1、memfunc2这类),每个函数都有3个重载版本——这些重载除了函数名不一样,签名完全一致。现在你写了caller1、caller2、caller3三个调用函数,每个都要根据传入的枚举值,调用对应成员函数的某个重载。目前你得给三个重载分别写一遍枚举到函数的映射,新增成员函数时要改三处,简直是维护噩梦对吧?
下面给你一个能一次性搞定映射、后续只需要加一行就能扩展的方案,核心思路是把每个成员函数的三个重载打包成一个“函数组”,让枚举直接映射到这个组,这样三个调用函数只需要从组里取对应的重载调用就行,不用重复写映射逻辑。
具体实现步骤
1. 先定义你的枚举类和目标类
#include <unordered_map> #include <string> // 对应每个成员函数的枚举类 enum class MemFuncEnum : unsigned int { Func1, Func2, // 以后新增函数只需要在这里加枚举项 }; // 包含多个带重载成员函数的类 class MyClass { public: // memfunc1的三个重载 void memfunc1(int arg) { /* 具体实现 */ } void memfunc1(int arg1, double arg2) { /* 具体实现 */ } int memfunc1(int arg1, double arg2, std::string arg3) { /* 具体实现 */ } // memfunc2的三个重载(签名和memfunc1完全一致) void memfunc2(int arg) { /* 具体实现 */ } void memfunc2(int arg1, double arg2) { /* 具体实现 */ } int memfunc2(int arg1, double arg2, std::string arg3) { /* 具体实现 */ } // ... 其他同模式的成员函数 };
2. 封装重载组的结构体
我们先把成员函数的三个重载类型定义好,再用一个结构体把它们打包:
// 封装单个成员函数的三个重载 struct MemFuncOverloads { // 定义三个重载的成员函数指针类型 using Overload1 = void (MyClass::*)(int); using Overload2 = void (MyClass::*)(int, double); using Overload3 = int (MyClass::*)(int, double, std::string); Overload1 overload1; Overload2 overload2; Overload3 overload3; };
3. 建立枚举到重载组的映射(只写一次!)
这里只需要维护这一处映射,新增成员函数时加一行就行:
// 枚举 -> 对应成员函数的重载组 映射表 const std::unordered_map<MemFuncEnum, MemFuncOverloads> func_map = { {MemFuncEnum::Func1, {&MyClass::memfunc1, &MyClass::memfunc1, &MyClass::memfunc1}}, {MemFuncEnum::Func2, {&MyClass::memfunc2, &MyClass::memfunc2, &MyClass::memfunc2}}, // 新增函数时,在这里加一行对应的映射即可 };
4. 实现调用函数(不用重复改!)
三个调用函数只需要查询一次映射表,取出对应重载调用:
// 调用第一个重载的函数 void caller1(MyClass& obj, MemFuncEnum func_enum, int arg) { auto it = func_map.find(func_enum); if (it != func_map.end()) { // 调用对应重载 (obj.*(it->second.overload1))(arg); } // 可选:处理枚举值不存在的异常情况 } // 调用第二个重载的函数 void caller2(MyClass& obj, MemFuncEnum func_enum, int arg1, double arg2) { auto it = func_map.find(func_enum); if (it != func_map.end()) { (obj.*(it->second.overload2))(arg1, arg2); } } // 调用第三个重载的函数 int caller3(MyClass& obj, MemFuncEnum func_enum, int arg1, double arg2, std::string arg3) { auto it = func_map.find(func_enum); if (it != func_map.end()) { return (obj.*(it->second.overload3))(arg1, arg2, arg3); } return -1; // 可选:默认返回值 }
优势
- 维护成本极低:新增成员函数时,只需要在枚举类加一项,再在映射表里加一行,三个调用函数完全不用动
- 无重复代码:映射逻辑只写一次,避免了之前三次重复写枚举判断的冗余
- 性能友好:用成员函数指针直接调用,没有额外的运行时开销
如果你的重载参数/返回值类型更复杂,还可以用模板进一步简化调用函数的写法,但上面的方案已经足够直观好用,适合大多数场景。
备注:内容来源于stack exchange,提问作者user-1
相关产品推荐
相关产品推荐

