实现作为仿函数的功能的优点和缺点

时间:2016-02-09 09:53:50

标签: c++ oop functor design-guidelines

我正与同事讨论一个只有一个公共方法的简单类的API。我最初去了:

class CalculateSomething
{
public:
  void operator()(const SomeObject &obj) const;

private:
  // ...
}

然而,我的同事反对使用operator(),并希望简单地命名方法'计算'为清楚起见。 虽然我没有发现这个论点令人信服,但它让我想到了利弊。

优点operator()

  • 课程精简,有一个明确的目的。一旦实例化,它基本上就像一个自由函数。
  • 它是一个仿函数,可以很容易地使用(例如STL算法)。
  • 当使用范围算法时,可以直接传递对象而不是通过函数指针,这使编译器能够内联代码。虽然不能保证,但通过函数指针完全禁止这种可能性。

缺点operator()

  • 如果不查看类名,该方法的作用就不太清楚了。 (我个人不同意,因为班级只有一种方法,因此从班级名称中明确其含义)
  • STL中的大多数算子都应该是无国籍的。我认为这是阻碍我的主要原因......

我很惊讶地发现,由于我认为这是一个非常常见的场景(一个班级,一个责任),因此我对此的搜索并没有带来太大的影响。因此,我真的很想听听其他人对此的看法。

2 个答案:

答案 0 :(得分:3)

如果lambdas 真的不是一个选项,那么您的选择应该取决于对象所承担的工作范围......以及您的编码约定或样式。您可以决定明确(请参阅Werolik的答案),如果该方法相对不熟悉且需要状态,这是一件好事,但

让我们从标准库中获取简单的用例......

  • std::hash:这是一个可以完成一项工作的函数对象,并且可以做得很好,没有相关的竞争
  • 还有更多 ...包括std::less及其分类

与所有这些相同的一点是,它们是动词 ...在我看来,如果您的课程与您发布的代码段完全相同,CalculateSomething表示行动对我来说,所以我总是可以将它实例化为CalculateSomething()(my_object...)

就像你引用的那样,它在使用STL算法本身和许多其他C ++库时非常方便。 如果你采用同事的方法,你可能不得不求助于使用std :: binds和lambdas,因为你想要适应'界面。

示例:

class CalculateSomething
{
    public:
         void operator()(const SomeObject &obj) const;
    private:
         // ...
}

class CalculateNothing
{
    public:
         void calculate(const SomeObject &obj) const;
    private:
         // ...
}

示例用法是:

std::for_each(container.begin(), container.end(), CalculateSomething());

针对

std::for_each(container.begin(), container.end(), [ c = CalculateNothing()](auto x) { c.calculate(x); });

我想我更喜欢前者。

答案 1 :(得分:1)

嗯,这里也是5美分。

首先,如果可能的话,我只使用lambda或free函数。您确定,您需要一个满足您需求的课程吗?

无论如何,假设需要上课。

  1. 我不喜欢使用operator()那么多。也许附加评论。
  2. 将它重命名为“SomethingCalculator”可能会很好 - 这不是一个对象吗?
  3. 您可以添加一种方法,例如“DoWork”,“Calculate”等。
  4. 这将使其更加明确。

    UPD。以上所有内容仍有争议,但我真正相信的是,添加足够的代码内文档会产生真正的差异,与方法名称无关。