成员函数和非成员函数有什么区别?

9

在操作类的函数中,哪些应该是成员函数,哪些应该是非成员函数?您有什么规则吗?例如,我有一个类,使用布尔矩阵表示迷宫。我正在编写一个名为 isConnected 的函数,用于验证迷宫中的两个点是否在同一区域(即从 A 到 B 是否可以行走)。

这个函数应该是成员函数还是非成员函数?有什么好的规则吗?

6个回答

16

2
我完全同意...而且我甚至不知道Sutter推荐了这个。 - D.Shawley

16

好的,两种方式都有一些争议。

支持非成员函数的理由:

  • 它提供了更好的封装性
  • 它允许更好的代码重用(std::find可以被重用于任何容器类型,因为它是一个自由函数。如果它是一个成员函数,每个容器都必须定义自己的)。
  • 它使很多通用编程技巧更容易实现。(container.begin()如果container是数组,则无效。这使得编写适用于容器的通用代码变得更加麻烦。但是begin(container)可以对任何类型进行有效定义,甚至是内置类型,如数组)。它还可以使混合通过组合更加简洁,因为它不需要用户通过成员"点"操作来获取要操作的混合对象。

支持成员函数的理由是:

  • 这是常见的。Java和C# 要求这样做,在很多程序员看来,成员函数与OOP同义。

而且...就只有这些了。 (但是这个论点不应该被低估。代码可读性很重要,如果人们发现成员版本更容易阅读,那么这是一个有力的支持论点。它只是不能产生更好的代码。从严格的"更好的代码"角度来看,可能情况下应优先考虑非成员函数。


11

何时将函数设计为成员函数:

  • 当函数与类具有逻辑上的耦合关系(例如迷宫连通性示例)时
  • 当函数需要访问私有或保护成员时,最好将其设计为成员函数而不是友元函数。

何时将函数设计为独立函数:

  • 当函数是通用的函数,可以模板化以自然地适用于其他类(请查看 <algorithm>头文件中的优秀示例)时

7
为什么?这些指南背后的理念是什么? - jalf
@jalf:你在帖子中提到非成员、非好友函数的好处,说得很有道理:编译器通过强制仅公共接口使用来改善封装性。非成员函数的一个潜在缺点是命名空间污染,至少对那些不喜欢创建丰富命名空间层次结构的人来说是这样。 - Mr Fooz

5
在这种情况下,我会选择成员函数。 我遵循的规则是,如果一个函数必须访问当前实例的内部状态,则应该是类的“领域”的一部分。 在这种情况下,A和B的连接取决于您的对象实例的状态。
当然,你可能最终会有一个类承担太多的责任。在这种情况下,保持简单因素发挥作用,您应该考虑您的类是否试图做太多事情。然后,最好有一个单独的类(例如,在您的情况下,ConnectednessEvaluator),其特定角色是持有可以遍历和处理Maze实例的算法。

4
我总是参考FAQ 13.9。这不是一门确切的科学,而是基于判断的。
简单地说,每当你需要访问类内部时,就应该使用成员函数,这是一种过度简化的说法。值得注意的例子是流插入/提取运算符(分别为>><<)以及二进制+
在你的示例中,isConnected是一个测试对象状态的方法,即一个检查器,是成为成员函数的理想候选。

0

我通常只会将非成员函数用于那些仅从成员函数内部调用的东西(不需要在类外可见),并且可以很好地操作类的公共成员和/或少量参数。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接