C++98环境下替换boost::function与boost::bind的技术问询
替代Boost.Function/Boost.Bind实现C++98下的成员函数存储
刚好解决过类似的场景!在C++98没有std::function的限制下,我们可以自己实现一个轻量级的包装器,用多态+模板来模拟Boost的功能,完美替换你当前的代码,具体步骤如下:
1. 定义统一的可调用抽象接口
首先我们需要一个基类,提供统一的调用入口,这样向量就能存储不同子类的实例(利用多态的类型擦除特性):
class VoidCallable { public: virtual ~VoidCallable() {} // 必须声明虚析构,保证子类能正确析构 virtual void operator()() = 0; // 纯虚函数,定义调用行为 };
2. 模板子类包装成员函数与实例
接下来写一个模板类,继承上面的基类,用来保存特定类的成员函数指针和实例指针:
template <typename T> class MemberFuncWrapper : public VoidCallable { public: // 构造函数传入成员函数和实例指针 MemberFuncWrapper(void (T::*func)(), T* instance) : m_memberFunc(func), m_instance(instance) {} // 重载()运算符,调用对应的成员函数 virtual void operator()() { (m_instance->*m_memberFunc)(); } private: void (T::*m_memberFunc)(); // 成员函数指针 T* m_instance; // 类实例指针 };
3. 修改App类的实现
现在把原来的boost::function<void()>向量换成我们的VoidCallable*向量,同时调整AddLoopFunc来创建包装器实例:
#include <vector> class App { public: App() {} template<class T> static void AddLoopFunc(void (T::*func)(), T* instance) { // 创建包装器实例并加入向量 loop_funcs.push_back(new MemberFuncWrapper<T>(func, instance)); } // 新增:遍历调用所有循环函数 static void RunLoop() { for (size_t i = 0; i < loop_funcs.size(); ++i) { (*loop_funcs[i])(); // 调用每个包装器的()运算符 } } // 新增:清理内存,避免泄漏 static void Cleanup() { for (size_t i = 0; i < loop_funcs.size(); ++i) { delete loop_funcs[i]; } loop_funcs.clear(); } static std::vector<VoidCallable*> loop_funcs; }; // 静态成员变量初始化 std::vector<VoidCallable*> App::loop_funcs;
4. 调用方式完全不变
你原来的调用代码不需要任何修改,直接用就行:
class MyClass { public: void Loop() { // 你的循环逻辑代码 } }; // 添加循环函数 MyClass myObj; App::AddLoopFunc(&MyClass::Loop, &myObj); // 运行所有循环函数 App::RunLoop(); // 程序结束时记得清理内存 App::Cleanup();
关键注意事项
- 内存管理:因为我们用
new创建了包装器实例,必须在合适的时机调用App::Cleanup()来释放内存,否则会造成内存泄漏。如果想避免手动管理,C++98里可以用std::auto_ptr,但向量存储auto_ptr时要注意拷贝所有权转移的问题,所以手动清理是最稳妥的方式。 - 线程安全:如果是多线程环境,访问
loop_funcs时需要加锁,这和你原来用Boost的版本要求一致。 - 兼容性:完全符合C++98标准,不需要任何第三方库,完美替换原来的
boost::bind和boost::function用法。
这个实现的核心思路和Boost.Function底层原理一致,都是用多态来实现类型擦除,把不同类型的成员函数统一成一个可调用的接口。
内容的提问来源于stack exchange,提问作者aquawicket




