如何调用存储在地图中的函子?

时间:2019-01-09 15:35:33

标签: c++

我有一个基类和一个类,应该是仿函数,像这样:

class BFunctor {};

class Add : public BFunctor {
public:
    int operator()(int x, int y) {
        return x + y;
    }
};

我打算创建几个这些子类,并将指向它们的指针存储在称为ops的映射中,如下所示:

map<string, BFunctor*> ops {};
Add add;
ops["sum"] = &add;

但是,这样做之后,为什么不能这样使用函数对象:

int x = ops["sum"](3, 5);

我的linter表示“明显调用的括号前的表达式必须具有(指针到)函数类型”

编译器说“错误:表达式不能用作函数”。

2 个答案:

答案 0 :(得分:7)

如评论中所述,您需要在BFunctor中定义要使用的成员,在这种情况下为operator()

class BFunctor {
    virtual int operator()(int x, int y) = 0;
};

class Add : public BFunctor {
public:
    int operator()(int x, int y) override {
        return x + y;
    }
};

您还需要取消引用存储在地图中的指针,因为指针 也没有operator()

std::map<string, BFunctor*> ops {};
Add add;
ops["sum"] = &add;

int x = (*ops["sum"])(3, 5);

但是您不必自己执行此操作。 already existsstandard library

#include <functional>
using BFunctor = std::function<int(int, int)>;
using Add = std::plus<int>;

int main() {
    std::map<string, BFunctor> ops {};
    Add add;
    ops["sum"] = add;

    int x = ops["sum"](3, 5);
}

答案 1 :(得分:5)

有几个问题。

正如注释中已经提到的,基类中没有operator(),因此,如果要通过指向它的指针进行调用,则必须提供一个(可能没有实现)并使其virtual,因此它可以分派到正确的派生类。

第二,您有一个指向类的指针,因此不能像通过函数指向指针那样通过它进行调用-您必须先取消引用它:

(*ops["sum"])(3, 5);

或者,如果需要:

ops["sum"]->operator()(3,5);

完整示例here