本文共 2230 字,大约阅读时间需要 7 分钟。
class WebBrower{ public: void ClearCach(); void ClearHistory(); void RemoveCookies();};
class WebBrower{ … void ClearEverything() { ClearCach(); ClearHistory(); RemoveCookies(); } …};
void ClearWebBrowser(WebBrower& w){ w.ClearCach(); w.ClearHistory(); w.RemoveCookies();}
现在的问题是,哪一种实现方式更好?也就是把它写成成员函数好,还是写成 non-member 、non-friend 函数好呢?
答案是 写成:non-member、non-friend 好。
首先,对于面向对象的一个误解:数据应该和操作数据的函数绑定在一起。如果按照这种解释,那么应该写成member的。但是实际上,面向对象强调的是封装性。
所谓封装就是不可见,越多东西被封装,能够看见它的人越少。越少的人看到它,我们就能够更大弹性的修改它。因此,封装性越好,我们改变实现的能力就越高。推崇封装的原因:我们能够改变事物,而只影响有限的客户。
我们计算能够访问该数据的成员函数以及其它函数的数量,作为一种粗糙的衡量。越多的函数能够访问它,它的封装性就越低。
例如:public数据,所有的函数都可以访问它,它就是毫无封装性的。private数据,只有friend和member函数可以访问它,它的封装性的高低,就和能够访问它的friend函数和member函数数量有关,数量越大,代表封装性越低,数量越小,代表封装性越高。
总之,在实现同一机能的情况下,面对使用member函数和non-member、non-friend函数的抉择时,后者提供更好的封装性。
这就从封装性的角度解释了上述例子。
关于上述论断,有两个需要注意的点。
第一: non-member、friend函数 和member函数时一样的,都可以访问私有数据。因此只是non-member、non-friend 的函数和member函数之间存在封装性程度的高低不一。
第二:可以将函数写成另一个类类的member函数。例如,可以使得ClearWebBrowser() 函数称为另外一个工具类的static member函数。non-member指的是不能将其写成浏览器类WebBrower 的成员函数。(这对于其它语言的程序员来说一个温暖的慰藉,因为有些语言只能将函数写到class内部。)
虽然可以将其写到其它类中,但是C++比较自然的做法是,将它写成一个non-member函数,并让它和浏览器类在同一个命名空间中。
这样的做法是由原因的:
namespace 和class 是不同的,namespace是可以跨越多个文件的,但是class却不能。class 内的是核心技能,但是便利函数只是提供便利的,可有可无的。即使没有便利函数,用户可以通过访问class进行相关的操作。因此说便利函数时外覆的。
一个类可以由不同的机能分化出拥有多个便利函数,与cookies管理有关的、与书签有关的、与打印有关的。用户可能只对其中一部分感兴趣,那就没有必须让他们之间存在编译相依的关系。可以将他们进行分离,与不同模块相关的便利函数写到不同的头文件中,这样用户对哪个模块感兴趣,就包含哪个头文件就可以了。
将所有便利函数放在多个头文件中但隶属于同一个命名空间,意味着客户可以轻松扩展这一组便利函数。他们需要增加什么便利函数时,也添加到这个命名空间就好。class就不能这样扩展。
注意: 原因一种组织代码的 方式也正是C++标准程序库的组织方式。C++并没有将所有的功能都写到一个头文件里,而是写成数十个头文件,每个头文件中包含某些机能。用户需要什么,就包含什么。这样形成一个编译相依的小系统。 这种分割机能的方式不适用于class成员函数,因为class必须整体定义,不能被分割成片段。
转载地址:http://qfgq.baihongyu.com/