能否在头文件中创建指向其他CPP文件类成员函数的指针?
问题解答
你直接写的代码无法通过编译,原因有两点:
- 指针类型错误:
Gif::myfunc是非静态成员函数,它的指针类型应该是void (Gif::*)(),而非普通函数指针void(*funcPtr)()——成员函数指针和普通函数指针是完全不同的类型,前者需要绑定类对象才能调用。 - 编译器无法识别符号:因为你没包含相关头文件,编译器不知道
Gif是什么类,也不知道myfunc的存在和签名,自然无法解析&Gif::myfunc。
但你的需求是可以实现的,只要在动态生成的anotherHeader.h中补充必要的声明,让编译器能识别函数的类型和所属范围即可,具体方案如下:
可行实现方式
1. 让Perl脚本生成类骨架和函数声明
既然anotherHeader.h是动态生成的,你可以让Perl脚本从定义Gif类的头文件中提取所有set函数的签名,在anotherHeader.h中生成Gif类的骨架定义(只包含需要的set函数声明),比如:
// anotherHeader.h 生成的内容 namespace myNamespace { class Gif { public: void setName(const std::string&); void setSize(int, int); void setOpacity(float); // ... 自动生成其他100多个set函数的声明 }; }
2. 创建函数指针映射
接着在anotherHeader.h中定义存储函数指针的映射容器,注意使用正确的成员函数指针类型:
#include <unordered_map> #include <string> // 定义成员函数指针类型别名,简化代码 using GifSetFuncPtr = void (myNamespace::Gif::*)(); // 全局映射(或用单例模式避免初始化顺序问题) std::unordered_map<std::string, GifSetFuncPtr> g_setFuncMap = { {"setName", &myNamespace::Gif::setName}, {"setSize", &myNamespace::Gif::setSize}, {"setOpacity", &myNamespace::Gif::setOpacity}, // ... 自动生成其他函数指针的键值对 };
3. 在abc.cpp中调用映射里的函数
在abc.cpp中包含真实的Gif类头文件和anotherHeader.h,就可以通过键调用对应的成员函数:
#include "abc.h" // 包含完整的Gif类定义 #include "anotherHeader.h" void callSetFunc(myNamespace::Gif& gifObj, const std::string& funcName) { auto it = g_setFuncMap.find(funcName); if (it != g_setFuncMap.end()) { // 调用成员函数指针,必须绑定类对象 (gifObj.*(it->second))(); // 如果是带参数的set函数,比如setSize,需要调整指针类型和调用方式: // (gifObj.*static_cast<void (myNamespace::Gif::*)(int,int)>(it->second))(100, 200); } }
额外注意事项
- 如果
set函数的参数类型不统一,无法用单一的成员函数指针类型存储,可以考虑用std::variant存储不同类型的指针,或者用void*暂存后在调用时强制转换回正确类型(后者需严格保证类型匹配,否则会出现未定义行为)。 - 全局变量存在初始化顺序问题,建议把映射放在静态函数中返回(Meyers单例模式),避免使用时映射未初始化:
std::unordered_map<std::string, GifSetFuncPtr>& getSetFuncMap() { static std::unordered_map<std::string, GifSetFuncPtr> map = { {"setName", &myNamespace::Gif::setName}, // ... }; return map; }
内容的提问来源于stack exchange,提问作者float
相关产品推荐
相关产品推荐

