C++通过map存储并调用类模板成员函数指针的方法
问题根源
你的代码有三处错误:
- 语法非法:成员指针调用运算符
.*的右侧必须是成员指针类型的表达式,你写的(proxy2.&(it->second))()把取地址符&插在对象和成员指针中间,完全不符合C++语法,直接触发编译错误。 - 类型不兼容:C++标准不保证成员函数指针可以和
void*互相转换,成员函数指针的内存长度、表示形式随继承模式、编译器实现变化,可能远大于普通void*的长度,强转存进void*属于未定义行为,随时可能崩溃。 - 野指针风险:你写的
myMap[0]= &memfnptr存的是局部变量memfnptr的栈地址,等赋值语句执行完,这个栈地址的内容随时可能被覆盖,后续取出来就是无效值。
修正方案
如果你的map只需要存储同一个类实例化出的同签名成员函数指针(比如你示例里全是SomeServiceProxy<int>的无参返回void的成员函数),直接把map的value类型设为对应的成员函数指针类型即可,不需要用void*做中间层。
修正后的可运行代码:
#include <iostream> #include <map> template<typename... extensions> class SomeServiceProxy { public: void DoSomething() { std::cout << "\ndoing sth\n"; } }; template<typename... extensions> using DoSomethingFnPtr = void (SomeServiceProxy<extensions...>::*)(); // map值类型直接定义为对应实例的成员函数指针类型 std::map<int, DoSomethingFnPtr<int>> myMap; int main() { SomeServiceProxy<int> proxy; DoSomethingFnPtr<int> memfnptr = &SomeServiceProxy<int>::DoSomething; proxy.DoSomething(); (proxy.*memfnptr)(); // 直接存成员函数指针的值,不要存局部变量的地址 myMap[0] = memfnptr; auto it = myMap.find(0); if(it != myMap.end() ){ SomeServiceProxy<int> proxy2; // 取出存储的成员指针,用.*运算符调用,注意括号不能漏 DoSomethingFnPtr<int> stored_ptr = it->second; (proxy2.*stored_ptr)(); } std::cout << std::endl; return 0; }
如果你需要在map里存储不同类、不同模板实例的成员函数,用类型擦除包装即可,比如借助std::function封装调用逻辑,不需要硬转void*:
#include <iostream> #include <map> #include <functional> template<typename... extensions> class SomeServiceProxy { public: void DoSomething() { std::cout << "\ndoing sth\n"; } }; // 统一包装为:传入对象地址,执行对应成员调用的可调用对象 std::map<int, std::function<void(void*)>> myMap; int main() { // 存入时包装好类型转换和调用逻辑 myMap[0] = [](void* inst) { auto* obj = static_cast<SomeServiceProxy<int>*>(inst); obj->DoSomething(); }; auto it = myMap.find(0); if(it != myMap.end() ){ SomeServiceProxy<int> proxy2; // 调用时传入对象实例地址即可 it->second(&proxy2); } std::cout << std::endl; return 0; }
注意事项
- 永远不要用
void*存储成员函数指针,这是C++开发中常见的未定义行为,哪怕个别编译器下临时跑通,换编译选项、类增加继承关系后会直接出现内存错误。 .*/->*运算符优先级低于函数调用运算符(),调用成员指针时必须把(实例.*成员指针)整体用括号包裹,再跟参数列表,否则会编译报错。
内容的提问来源于stack exchange,提问作者Monica Dumescu
相关产品推荐
相关产品推荐

