You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.15 07:56:36