调用派生类的函数调用运算符时避免使用指针

Avoiding pointers when calling the function call operator of the derived class

本文关键字:指针 运算符 派生 函数调用 调用      更新时间:2023-10-16

我有一个关于函数对象继承的问题。

我想这肯定是在 Stack Overflow 上问了太多次的,但措辞相似的问题数量之多使我几乎不可能找到任何东西。

假设我有一个基本的抽象类:

class BinaryOperation
{
public:
    virtual int operator()(int a, int b) = 0;
};

从中派生出两个新类:

class Plus : public BinaryOperation
{
public:
    virtual int operator()(int a, int b)
    {
        return a + b;
    };
};
class Minus : public BinaryOperation
{
public:
    virtual int operator()(int a, int b)
    {
        return a - b;
    };
};

我想使用 std::map 将字符串映射到派生自同一类的各种函子:

我的第一个方法是

std::map<std::string, BinaryOperation> operator_map;
operator_map["+"] = Plus();
operator_map["-"] = Minus();
operator_map["-"](5, 2); 

显然,这不起作用,因为我们不能实例化抽象类。

如果我使用指向基类的指针,它可以正常工作,但看起来更笨拙,并且由于我们必须new对象,这使得它更容易发生内存泄漏(我们必须手动delete对象)

std::map<std::string, BinaryOperation*> operator_map;
operator_map["+"] = new Plus();
operator_map["-"] = new Minus(); 
std::cout << (*operator_map["-"])(5, 2)

在不牺牲 RAII 优势的情况下实现此功能的首选方法是什么?

只需制作一张std::stringstd::function<int(int, int)>的地图。这允许您取消任何公共基类,因为函数对象提供多态性:

struct Plus {
  int operator()(int a, int b) const{ return a+b; }
};
struct Minus {
  int operator()(int a, int b) const{ return a-b; }
};
int main()
{
  std::map<std::string, std::function<int(int,int)>> opMap;
  using namespace std::placeholders;
  opMap["-"] = Minus();
  opMap["+"] = Plus();
  std::cout << opMap["-"](5,2) << std::endl;
  std::cout << opMap["+"](5,6) << std::endl;
}

请注意,标准库提供了在 functional 标头中实现算术运算的函子,因此您不必自己实现MinusPlus

opMap["-"] = std::minus<int>();
opMap["+"] = std::plus<int>();