版权声明:仅供参考与学习交流 https://blog.csdn.net/lym940928/article/details/81951767
条款23:宁以non-member、non-friend替换member函数
Prefer non-member non-friend functions to member.
本章分为两个部分。
假设有一个class用来表示网页浏览器。这样的class可能提供的众多函数中:
- 有一些用来清除下载元素高速缓存区(cache of downloaded elements)
- 清除访问过的URLs的历史记录(history of visited URLs)
- 清除系统中的所有cookies
class WebBrowser {
public:
...
void clearCache();
void clearHistory();
void removeCookies();
...
};
因此,用户可能会觉得使用一个操作来执行这些任务,因此WebBrowser也提供这样一个函数:
- member函数
class WebBrowser {
public:
...
void clearEverything(); //调用上述的三个函数
};
同时,这个机能也可以通过一个non-memebr函数调用适当的member函数而提供:
- non-member函数
void clearBrowser (WebBrowser& wb)
{
wb.clearCache();
wb.clearHistory();
wb.removeCookies();
}
那么,对于上面两个办法,哪一种较好呢?
首先,对于面向对象守则的要求,数据及操作数据的那些函数应该被捆绑在一起。这就意味着使用member函数可能是一个比较好的选择。然而事实上并非如此!
- 面向对象守则要求数据应该尽可能地被封装,而与直观相反的是,member函数clearEverything所带来的封装性比non-member函数clearBrowser要低。
此外,提供non-member函数可允许对WebBrowser相关机能有较大的包裹弹性(packaging flexibility),而那最终导致较低的编译相依度,增加WebBrowser的可延伸性。
- 因此,许多方面non-member做法比member做法好。
首先,从封装开始讨论。
- 如果某些东西被封装,它就不再可见。越多的东西被封装,就越少的人可以看见。而越少的人可以看到它,我们就有越大的弹性去改变它,因为我们的改变仅仅直接影响看到改变的那些人事物。因此,越多的东西被封装,我们改变这些东西的能力就越大。简而言之,封装使得我们能够改变事物而只影响有限的用户。
然后,考虑对象内的数据。
- 越少的代码可以看到数据(即访问到它),越多的数据就可以封装,而我们就越能自由地改变对象数据,例如改变成员变量的数量、类型等。简而言之,越多的函数可以访问这个数据,它的封装性就越低。
在上一个条款22中可以得知,成员变量应该是private,因为如果它们不是private,就会有无限量的函数可以访问到它们,它们也就毫无封装性。
- 能够访问private成员变量的函数只有class的member函数加上friend函数。
对于member函数,它可以访问class内的:
- private数据
- private函数
- enums
- typedefs
- 等等
而对于non-member函数,它无法访问上述的任何一个。
如果我们需要在member函数和non-member函数中选择,而且两者提供相同的机能,则:
- 导致较大封装性的是non-member non-friend函数,因为它并不会增加“能够访问class内的private”的函数数量。
因此,这也就解释了为什么clearBrowser(non-member non-friend函数)比clearEverything(member函数)更受欢迎:
它导致WebBrowser class有有较大的封装性。