在实例方法和自由函数之间进行选择?

Sta*_*ked 14 c++

向类添加功能可以通过添加方法或定义将对象作为其第一个参数的函数来完成.我认识的大多数程序员会选择添加实例方法的解决方案.

但是,我有时更喜欢创建一个单独的功能.例如,在下面的示例代码中Area,Diagonal定义为自由函数而不是方法.我发现这种方式更好,因为我认为这些功能提供增强而不是核心功能.

这被认为是好/坏的做法吗?如果答案是"它取决于",那么在添加方法或定义单独函数之间决定的规则是什么?

class Rect
{
public:
    Rect(int x, int y, int w, int h) :
        mX(x), mY(y), mWidth(w), mHeight(h)
    {
    }

    int x() const { return mX; }

    int y() const { return mY; }

    int width() const { return mWidth; }

    int height() const { return mHeight; }

private:
    int mX, mY, mWidth, mHeight;
};


int Area(const Rect & inRect)
{
    return inRect.width() * inRect.height();
}


float Diagonal(const Rect & inRect)
{
    return std::sqrt(std::pow(static_cast<float>(inRect.width()), 2) + std::pow(static_cast<float>(inRect.height()), 2));
}
Run Code Online (Sandbox Code Playgroud)

Jer*_*fin 15

GoTW#84探讨了这个问题std::string.他倾向于相反的观点:大多数职能应该是全球性的,除非他们真的需要成为成员.

我会说大多数现代C++倾向于同一个想法.例如,如果你看看Boost,可以使用免费函数完成相当多的工作.

  • 我喜欢文章中包含Scott Meyers的这句话:>我将从妙语开始:如果您正在编写一个可以作为成员或非朋友非成员实现的功能,您应该更喜欢将其实现为非成员函数.该决定增加了类封装.当你考虑封装时,你应该考虑非成员函数. (4认同)
  • 我让Scott Meyers站在我一边.我现在可以死了:) (4认同)
  • @jmucchiello:如果你将它放在相关的命名空间中,那么(无论好坏)它将由ADL找到.所以你可以做`Geometry :: Rect r(12,23); std :: cout << Area(r);`. (3认同)
  • 我唯一可能的是命名空间污染.float Geometry :: Area(const Geometry :: Rect&r)比float Geometry :: Rect :: Area()好吗?您真的不希望自由函数区域位于全局名称空间中,因此您需要放入名称空间.在那一点上,它看起来像一个静态类函数. (2认同)
  • @jmucchiello:是的,大多数免费函数应该在命名空间中.我不认为这看起来像静态成员函数 - 我习惯于`x :: y`意思是"命名空间x中的函数y". (2认同)