含自定义函数的类编译错误排查及实现方案咨询
这个编译错误的核心是你混淆了类的非静态成员函数和普通函数的类型本质差异:非静态成员函数会隐含一个this指针参数,它的实际类型是int (SomeClass::*)(int),而不是你预期的int (*)(int)(普通函数指针)。boost::function<int(int)>期望的是一个接受单个int参数并返回int的可调用对象,直接赋值非静态成员函数会因为签名不匹配失败。
同时还要提醒你:原代码里的析构函数写法有误,正确的写法应该是SomeClass::~SomeClass()而不是~SomeClass::SomeClass()。
下面给你几个可行的解决思路:
方法1:用boost::bind绑定this指针
通过boost::bind把当前对象的this指针和成员函数绑定,补全隐含的this参数,就能适配boost::function的签名:
SomeClass::SomeClass(){ // _1是boost的占位符,表示第一个参数会被传递给DefaultFunction someFunction = boost::bind(&SomeClass::DefaultFunction, this, _1); }
如果想让SetFunction支持更多类型的可调用对象(比如其他类的成员函数、lambda),建议把参数改成boost::function<int(int)>,这样灵活性更高:
void SomeClass::SetFunction(boost::function<int(int)> f){ someFunction = f; }
使用示例(比如绑定外部类的成员函数):
class OtherClass { public: int Double(int x) { return x * 2; } }; void MyProgram(){ SomeClass s; OtherClass o; // 绑定OtherClass的成员函数到s的someFunction s.SetFunction(boost::bind(&OtherClass::Double, &o, _1)); }
方法2:把DefaultFunction改为静态成员函数
如果DefaultFunction不需要访问类的非静态成员变量或成员函数,可以将其声明为静态成员函数。静态成员函数没有隐含的this指针,类型就是int (*)(int),可以直接赋值给boost::function<int(int)>:
class SomeClass{ private: boost::function<int(int)> someFunction; static int DefaultFunction(int i); // 改为静态 public: // ... 其他成员不变 }; // 实现也不需要修改,只是类型变成普通函数指针 int SomeClass::DefaultFunction(int i){ return i+1; } SomeClass::SomeClass(){ someFunction = DefaultFunction; // 现在可以直接赋值 }
更优方案:改用C标准库(C11+)
如果你的编译器支持C++11或更高版本,完全可以放弃boost依赖,使用标准库的std::function和std::bind,代码更通用且无需额外依赖:
#include <functional> class SomeClass{ private: std::function<int(int)> someFunction; int DefaultFunction(int i); public: SomeClass(); ~SomeClass(); void SetFunction(std::function<int(int)> f); }; int SomeClass::DefaultFunction(int i){ return i+1; } SomeClass::SomeClass(){ // 使用std::placeholders::_1作为参数占位符 someFunction = std::bind(&SomeClass::DefaultFunction, this, std::placeholders::_1); } SomeClass::~SomeClass(){ // 析构函数可以留空,编译器会自动生成默认实现 } void SomeClass::SetFunction(std::function<int(int)> f){ someFunction = f; } void MyProgram(){ SomeClass s; // 还可以直接用lambda表达式设置自定义函数 s.SetFunction([](int x){ return x * 3; }); }
这个方案还支持直接传入lambda表达式,比boost的写法更简洁灵活。
内容的提问来源于stack exchange,提问作者Jack Rolph

