12

我正在与一位同事讨论只有一个公共方法的简单类的 API。我最初选择的是:

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

private:
  // ...
}

但是,我的同事反对使用 operator() 并希望为清楚起见简单地将方法命名为“计算”。虽然我觉得这个论点没有说服力,但它让我想到了利弊。

优点 operator()

  • 该类是精简的,并且有一个明确定义的目的。一旦实例化,它基本上充当一个自由函数。
  • 它是一个仿函数,可以很容易地使用(例如 STL 算法)。
  • 当将它与范围算法一起使用时,可以直接传递对象而不是通过函数指针,这使编译器能够内联代码。虽然不能保证,但通过函数指针传递它会完全抑制这种可能性。

缺点 operator()

  • 如果不查看类名,则不太清楚该方法的作用。(我个人不同意,因为该类只有一种方法,因此从类名中可以清楚地看出其含义)
  • STL 中的大多数函子都应该是无状态的。我认为这是阻碍我前进的主要原因......

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

4

2 回答 2

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); });

我想我更喜欢前者。

于 2016-02-09T10:28:26.537 回答
1

好吧,这也是我的 5 美分。

首先,如果可能的话,我会简单地使用 lambda 或 free 函数。你确定,你需要一个课程来满足你的需要吗?

无论如何,假设该课程是必需的。

  1. 我不太喜欢使用 operator() 。也许还有其他评论。
  2. 将它重命名为 ' ' 可能会很好SomethingCalculator- 它不是一个对象吗?
  3. 比你可以添加一个方法,比如' DoWork',' Calculate'或其他什么。

这将使它更加明确。

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

于 2016-02-09T10:36:34.403 回答