- 它促进了封装,因为需要访问类内部的代码更少。
- 它使编写函数模板更容易,因为您不必每次猜测某个函数是否是成员。
- 它使类保持小巧,从而更易于测试和维护。
虽然我看到这些论点的价值,但我看到一个巨大的缺点:我的IDE无法帮助我找到这些函数!每当我有某种对象,并且我想查看它上面可用的操作时,我不能只输入“pMysteriousObject->
”并获得成员函数列表。
虽然我看到这些论点的价值,但我看到一个巨大的缺点:我的IDE无法帮助我找到这些函数!每当我有某种对象,并且我想查看它上面可用的操作时,我不能只输入“pMysteriousObject->
”并获得成员函数列表。
Scott Meyers与Sutter有相似的观点,详情请见这里。
他还明确表示:
"基于他对各种类似字符串的类的工作,Jack Reeves观察到,即使它们可以是非友元非成员函数,某些函数在作为非成员函数时感觉不太对。一个类的“最佳”接口只能通过平衡许多竞争关注点来找到,其中封装程度只是其中之一。"
如果一个函数在作为成员函数时“很自然”,那么就将其定义为成员函数。同样,如果它并不真正是主接口的一部分,并且在作为非成员函数时“很自然”,那么就将其定义为非成员函数。
需要注意的是,在例如operator==()的重载版本中,语法保持不变。因此,在这种情况下,除非它确实需要访问私有成员(根据我的经验,这种情况很少发生),否则您没有理由不将其定义为非成员非友元浮动函数,并在与类声明相同的位置声明它。即使如此,您也可以将operator!=()定义为非成员函数,并以operator==()为基础进行定义。
确实,外部函数不应该成为接口的一部分。理论上,您的类应该只包含数据并公开其预期的接口,而不是实用函数。将实用函数添加到接口中只会增加类代码库并使其难以维护。我目前维护一个具有约50个公共方法的类,这简直是疯狂。
现实情况下,我同意这很难强制执行。通常更容易只需向类添加另一个方法,尤其是如果您正在使用可以轻松向现有类添加新方法的IDE。
为了保持我的类简单并仍能够集中外部函数,我经常使用与我的类一起工作的实用程序类,甚至是命名空间。 我首先创建将包装我的数据并公开最简单可能的接口的类。然后,我为每个要使用该类执行的任务创建一个新类。
例如:创建一个Point类,然后添加一个PointDrawer类来将其绘制到位图中,PointSerializer类来保存它等等。
::prefix
或者
namespace::prefix
我本以为IDE实际上会帮助你。
IDE从列表中隐藏了受保护的函数,因为它们对公众不可用,正如类的设计者所期望的那样。
如果您在类的范围内并键入this->,则受保护的函数将显示在列表中。