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

在map中存储函数指针报错,求错误原因及修复方案

问题:类成员map存储成员函数指针时触发E0289错误

尝试在类的map成员中存储成员函数指针,编译时出现E0289错误,但如果把相关逻辑放到main函数里就能正常运行,需要解释错误原因并提供修复方案。

原代码

#include <boost/variant.hpp>
#include <map>
#include <iostream>
#include <map>
using namespace boost;
class obj {
public:
    int num1;
    int num2;
    std::string s1;
    std::string s2;
};
typedef boost::variant<int, float, double, std::string> MultiType;
typedef MultiType(*FnPtr)(obj);

class c {
public:
    MultiType add(obj o);
    std::map<std::string, FnPtr> metricToFuncMap = { { "i", add } };
};
MultiType c::add(obj o) {
    { MultiType x;  x = o.num1 + o.num2; return x; }
}

int main() {
    obj o;
    //add
    MultiType d;
    d = 1;
    o.num1 = 1;
    o.num2 = 2;
    //concat
    o.s1 = "hello";
    o.s2 = "world";
    c c;
    MultiType x = c.metricToFuncMap["i"](o);
    std::cout << get<int>(x);
    return 0;
}

错误信息

E0289   no instance of constructor "std::map<_Kty, _Ty, _Pr, _Alloc>::map [with _Kty=std::string, _Ty=FnPtr, _Pr=std::less<std::string>, _Alloc=std::allocator<std::pair<const std::string, FnPtr>>]" matches the argument list

错误原因

核心问题是类的非静态成员函数和普通函数指针不兼容:

  • 你定义的FnPtr是普通函数指针类型,指向的函数无需依赖对象实例就能调用。
  • 但c::add是类的非静态成员函数,这类函数会隐式携带一个this指针参数,用来指向调用它的对象实例,实际类型是MultiType (c::*)(obj),和FnPtr完全不匹配,因此无法存入map。
  • 若把逻辑放到main里用普通非成员函数,类型匹配就不会报错。

修复方案

方案1:将成员函数改为静态函数

如果add不需要访问类的非静态成员变量,改成静态成员函数即可——静态函数没有隐式this指针,类型和FnPtr匹配:

#include <boost/variant.hpp>
#include <map>
#include <iostream>
#include <map>
using namespace boost;
class obj {
public:
    int num1;
    int num2;
    std::string s1;
    std::string s2;
};
typedef boost::variant<int, float, double, std::string> MultiType;
typedef MultiType(*FnPtr)(obj);

class c {
public:
    static MultiType add(obj o); // 改为静态函数
    std::map<std::string, FnPtr> metricToFuncMap = { { "i", add } };
};
MultiType c::add(obj o) {
    MultiType x;  
    x = o.num1 + o.num2; 
    return x;
}

int main() {
    obj o;
    o.num1 = 1;
    o.num2 = 2;
    c c;
    MultiType x = c.metricToFuncMap["i"](o);
    std::cout << get<int>(x);
    return 0;
}

方案2:使用成员函数指针类型存储

必须保留非静态成员函数时,把map的value类型改成成员函数指针,调用时结合对象实例:

#include <boost/variant.hpp>
#include <map>
#include <iostream>
#include <map>
using namespace boost;
class obj {
public:
    int num1;
    int num2;
    std::string s1;
    std::string s2;
};
typedef boost::variant<int, float, double, std::string> MultiType;
// 定义类c的成员函数指针类型
typedef MultiType (c::*MemFnPtr)(obj);

class c {
public:
    MultiType add(obj o);
    std::map<std::string, MemFnPtr> metricToFuncMap = { { "i", &c::add } }; // 取成员函数地址
};
MultiType c::add(obj o) {
    MultiType x;  
    x = o.num1 + o.num2; 
    return x;
}

int main() {
    obj o;
    o.num1 = 1;
    o.num2 = 2;
    c c;
    // 调用成员函数指针需要绑定对象实例
    MultiType x = (c.*c.metricToFuncMap["i"])(o);
    std::cout << get<int>(x);
    return 0;
}

方案3:使用std::function封装(更灵活)

需要兼容lambda、绑定参数等场景时,用std::function封装:

#include <boost/variant.hpp>
#include <map>
#include <iostream>
#include <functional> // 引入std::function头文件
using namespace boost;
class obj {
public:
    int num1;
    int num2;
    std::string s1;
    std::string s2;
};
typedef boost::variant<int, float, double, std::string> MultiType;

class c {
public:
    MultiType add(obj o);
    // 用lambda绑定当前对象的this,封装成std::function
    std::map<std::string, std::function<MultiType(obj)>> metricToFuncMap = {
        {"i", [this](obj o) { return this->add(o); }}
    };
};
MultiType c::add(obj o) {
    MultiType x;  
    x = o.num1 + o.num2; 
    return x;
}

int main() {
    obj o;
    o.num1 = 1;
    o.num2 = 2;
    c c;
    MultiType x = c.metricToFuncMap["i"](o);
    std::cout << get<int>(x);
    return 0;
}

内容的提问来源于stack exchange,提问作者Anees

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.17 21:10:52