可以通过添加方法或定义将对象作为其第一个参数的函数来向类添加功能。我认识的大多数程序员会选择添加实例方法的解决方案。
但是,我有时更喜欢创建一个单独的功能。例如,在下面的示例代码中,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));
}
答案 0 :(得分:15)
GoTW #84针对std::string
探讨了这个问题。他倾向于相反的观点:除非他们真的需要成为成员,否则大多数职能应该是全球性的。
我认为大多数现代C ++倾向于同一个想法。例如,如果你看看Boost,可以使用免费函数完成相当多的工作。
答案 1 :(得分:2)
如果你想将它与其他不相关的类一起使用,它应该是一个带有覆盖的自由函数。
例如,您可以覆盖float Area( Hexagon const & )
和float Diagonal( Hexagon const & )
。 x
,y
,width
和height
对不同的形状有不同的含义。
抽象基类(或不相关的同音词方法)是另一种解决方案,但免费函数是用户可扩展的,因此用户在添加自己的东西后可以有效地获得更加统一的界面。
避免使用名称含糊不清的自由函数,以便不相关的函数不会成为“竞争”覆盖。
答案 2 :(得分:1)
我会说这取决于你的目标是什么。如果该函数是成员函数,那么您可以使用。和 - &gt;用它表示法,并且它更好地与班级融为一体。它还允许多态性。如果您希望您的函数是虚函数,则它必须是成员函数。
然而,有一种观点认为,只有在需要时才能使函数成员函数更好地封装。因此,如果函数实际上不需要访问成员变量(可能是因为它可以完成它只需要公共函数执行的操作),那么您将它作为一个单独的函数,而不是该类的成员。这样即使偶然也不会弄乱内部。
另一个考虑因素是,如果它不是成员函数,则必须担心是否可以或应该将其他类型转换为现在是函数的第一个参数的类型。有时这是可取的,有时不是。如果它是一个成员函数,那么这不是问题(或者是机会,取决于你想要做什么)。
就个人而言,我不喜欢与班级分开的函数,但是当你无法控制类时,你常常被迫以这种方式编写函数,或者由于兼容性的原因你不能改变函数或者诸如此类。
真的,我认为这取决于你最重要的事情,以及你真正想要做的事情。我认为将该函数作为该类的一部分使其更易于使用和更面向对象,但如果您限制对类的私有成员的访问权限,则可以更好地包含该函数。