派生类成员函数无法隐式转换为基类成员函数的解决方案咨询
解决方案:通过模板成员函数简化回调注册
要让用户直接使用r1.register_callback_func(this, &mymap::user_function);的写法,核心是让register_callback_func能接受任意派生自regmap的类的成员函数指针,无需手动强制转换。可以通过模板成员函数实现这一点,具体修改如下:
修改后的完整代码
#include <iostream> #include <string> #include <functional> using namespace std; class regmap; class reg { public: std::function<void(reg)> callback_func; // 改为模板函数,支持任意派生自regmap的类的成员函数指针 template<typename MapType> void register_callback_func(MapType* map, void (MapType::*func)(reg)) { callback_func = std::bind(func, map, std::placeholders::_1); } reg(string name) : name(name) { callback_func = nullptr; } void read() { if (callback_func) { callback_func(*this); } } string name; }; class regmap { public: regmap() {} virtual ~regmap() {} }; class mymap : public regmap { public: mymap() : regmap() { reg r1("r1"); // 直接调用,无需强制转换 r1.register_callback_func(this, &mymap::user_function); r1.read(); } void user_function(reg r) { cout << " ....user_function...." << endl; } }; int main() { mymap map; return 0; }
关键修改说明
- 移除固定的funcPtr类型:不再使用
typedef void(regmap::*funcPtr)(reg),因为这个类型只能接受基类regmap的成员函数指针,派生类的无法隐式转换。 - 替换为模板成员函数:
register_callback_func变为模板函数,参数MapType会由编译器自动推导为调用时传入的类类型(比如mymap),这样就能直接接受void (MapType::*)(reg)类型的成员函数指针。 - 内部bind逻辑不变:依然用
std::bind将成员函数和对象实例绑定,最终赋值给std::function<void(reg)类型的callback_func,保证后续read()调用时的正确性。
为什么这个方案可行?
模板参数MapType会适配任意派生自regmap的类,编译器在编译期会根据传入的this(mymap*类型)和&mymap::user_function(void (mymap::*)(reg)类型)自动推导MapType为mymap,从而避免了派生类到基类成员函数指针的转换问题,让用户的调用代码保持简洁。
内容的提问来源于stack exchange,提问作者KPathak
相关产品推荐
相关产品推荐

