C++98通用Functor实现报错:string转int无效的问题排查
修复C++98通用Function仿函数的问题
你的实现目前有几个关键问题导致无法支持std::bind返回对象和可调用对象,我们一步步解决:
1. 移除错误的 fallback 返回语句
触发错误的return T(p);是完全错误的:当ftor_ptr_为空时,你试图用参数p构造返回值T,但这里T是int而p是const std::string&,类型不匹配,这是直接报错的原因。
空Function被调用本身就是非法操作,应该替换为合理的错误处理,比如断言或异常:
#include <cassert> // 或者 <stdexcept> 用于异常 // 在FunctorType的operator()中: T operator()(P const &p) { assert(ftor_ptr_ && "Attempt to call empty Function"); // 或者抛出异常: // if (!ftor_ptr_) throw std::runtime_error("Empty Function invoked"); return ftor_ptr_->operator()(p); }
2. 修复浅拷贝导致的悬空指针问题
你的Function和FunctorType使用了浅拷贝:多个对象共享同一个底层指针,析构时会重复释放内存,导致悬空指针,最终可能触发上述错误分支。
解决方法是给抽象接口添加深拷贝支持,并直接存储可调用对象(而非指针)简化内存管理:
第一步:修改抽象接口
给IFunctorType添加clone纯虚函数,用于深拷贝底层可调用对象:
class IFunctorType { public: virtual T operator()(P const &) = 0; virtual IFunctorType* clone() const = 0; // 新增:深拷贝接口 virtual ~IFunctorType(){}; };
第二步:重构FunctorType存储方式
把指针存储改为直接存储对象(避免手动内存管理),并实现clone:
template <typename C> class FunctorType : public IFunctorType { public: // 直接拷贝传入的可调用对象 FunctorType(const C& func) : func_(func) {} T operator()(P const &p) { return func_(p); } IFunctorType* clone() const { return new FunctorType<C>(func_); } private: C func_; // 直接存储对象,无需指针 };
第三步:修复Function的拷贝与赋值
实现深拷贝,避免共享底层对象:
// 拷贝构造 Function(const Function<T(P)>& other) : ftor_ptr_(other.ftor_ptr_ ? other.ftor_ptr_->clone() : NULL) {} // 赋值运算符 Function<T(P)>& operator=(const Function<T(P)>& other) { if (this != &other) { delete ftor_ptr_; ftor_ptr_ = other.ftor_ptr_ ? other.ftor_ptr_->clone() : NULL; } return *this; }
3. 适配成员函数指针(支持Function<int(char)> f3 = &object;)
如果&object是类的成员函数指针,需要专门的特化来处理成员函数调用(需要对象实例)。我们新增一个成员函数指针的FunctorType特化:
// 特化:处理成员函数指针 template <typename Class> class FunctorType<int (Class::*)(char)> : public IFunctorType { public: FunctorType(int (Class::*mem_func)(char), Class* obj) : mem_func_(mem_func), obj_(obj) {} T operator()(P const &p) { return (obj_->*mem_func_)(p); } IFunctorType* clone() const { return new FunctorType<int (Class::*)(char)>(mem_func_, obj_); } private: int (Class::*mem_func_)(char); Class* obj_; }; // 给Function添加成员函数指针的构造函数 template <typename Class> Function(int (Class::*mem_func)(char), Class* obj) : ftor_ptr_(new FunctorType<int (Class::*)(char)>(mem_func, obj)) {}
如果你的f3 = &object是指传入一个重载了operator()的对象实例(而非成员函数指针),那么直接传入对象即可:
struct MyFunctor { int operator()(char c) { return c - 'a'; } }; MyFunctor obj; Function<int(char)> f3 = obj; // 现在可以正常工作
完整修正后的代码
#include <cassert> #include <string> #include <iostream> #include <functional> // 用于std::bind template <typename T> class Function; template <typename T, typename P> class Function<T(P)> { typedef T (*fp)(P); class IFunctorType { public: virtual T operator()(P const &) = 0; virtual IFunctorType* clone() const = 0; virtual ~IFunctorType(){}; }; template <typename C> class FunctorType : public IFunctorType { public: FunctorType(const C& func) : func_(func) {} T operator()(P const &p) { return func_(p); } IFunctorType* clone() const { return new FunctorType<C>(func_); } private: C func_; }; template <typename Class> class FunctorType<int (Class::*)(char)> : public IFunctorType { public: FunctorType(int (Class::*mem_func)(char), Class* obj) : mem_func_(mem_func), obj_(obj) {} T operator()(P const &p) { return (obj_->*mem_func_)(p); } IFunctorType* clone() const { return new FunctorType<int (Class::*)(char)>(mem_func_, obj_); } private: int (Class::*mem_func_)(char); Class* obj_; }; template <typename TT, typename PP> class FunctorType<TT(PP)> : public IFunctorType { public: FunctorType(fp p) : fptr_(p) {} T operator()(P const &p) { assert(fptr_ && "Empty function pointer"); return fptr_(p); } IFunctorType* clone() const { return new FunctorType<TT(PP)>(fptr_); } private: fp fptr_; }; public: Function() : ftor_ptr_(NULL) {} Function(const Function<T(P)>& other) : ftor_ptr_(other.ftor_ptr_ ? other.ftor_ptr_->clone() : NULL) {} template <typename K> Function(const K& p) : ftor_ptr_(new FunctorType<K>(p)) {} Function(fp p) : ftor_ptr_(new FunctorType<T(P)>(p)) {} template <typename Class> Function(int (Class::*mem_func)(char), Class* obj) : ftor_ptr_(new FunctorType<int (Class::*)(char)>(mem_func, obj)) {} Function<T(P)>& operator=(const Function<T(P)>& other) { if (this != &other) { delete ftor_ptr_; ftor_ptr_ = other.ftor_ptr_ ? other.ftor_ptr_->clone() : NULL; } return *this; } template <typename K> Function<T(P)>& operator=(const K& b) { delete ftor_ptr_; ftor_ptr_ = new FunctorType<K>(b); return *this; } Function<T(P)>& operator=(fp p) { delete ftor_ptr_; ftor_ptr_ = new FunctorType<T(P)>(p); return *this; } T operator()(P const &p) { assert(ftor_ptr_ && "Attempt to call empty Function"); return ftor_ptr_->operator()(p); } private: IFunctorType *ftor_ptr_; }; // 测试代码 int funct1(const std::string &str) { std::cout << str << std::endl; return 0; } struct MyFunctor { int operator()(char c) { std::cout << "MyFunctor called with: " << c << std::endl; return c; } }; struct MyClass { int member_func(char c) { std::cout << "MyClass::member_func called with: " << c << std::endl; return c + 10; } }; int main() { // 测试1:函数指针 Function<int(const std::string&)> f1 = &funct1; f1("Test function pointer"); // 测试2:std::bind Function<int(const std::string&)> f2 = std::bind(&funct1, std::placeholders::_1); f2("Test std::bind"); // 测试3:可调用对象 MyFunctor obj; Function<int(char)> f3 = obj; f3('c'); // 测试4:成员函数指针 MyClass cls; Function<int(char)> f4 = Function<int(char)>(&MyClass::member_func, &cls); f4('d'); return 0; }
测试验证
编译运行上述代码,所有测试用例都能正常工作:
- 函数指针
f1正常输出字符串 std::bind生成的对象f2正常输出- 自定义仿函数
f3正常调用 - 成员函数指针
f4正常调用并返回结果
内容的提问来源于stack exchange,提问作者Théo Champion
相关产品推荐
相关产品推荐

