Effective C++ 条款23:设计与声明——宁以 non-member、non-friend 替换 member 函数

想象有个 class 用来表示网页浏览器。这样的 class 可能提供的众多函数中,有一些用来清除下载元素高速缓存区(cache of download elements)、清除访问过的 URLs 的历史记录(history of visited URLs)、以及移除系统中的所有cookies,如下所示:

class WebBrowser{
public:
	...
	void clearCache();
	void clearHistory();
	void removeCookies();
	...
};

许多用户可能会想整个执行这些动作,所以 WebBrowser 也提供这样一个函数:

class WebBrowser{
public:
	...
	void clearEverything();			// 调用 clearCache, clearHistory 和 removeCookies
	...
};

当然,这一机能也可以由一个 non-member 函数调用适当的 member 函数而提供出来:

void clearBrowser(WebBrowser& wb){
	wb.clearCache();
	wb.clearHistory();
	wb.removeCookies();
}

那么这两种实现方式,哪一种更胜一筹呢?
面向对象守则要求,数据以及操作数据的那些函数应该被捆绑在一块,这意味着它建议 member 函数是较好的选择。不幸的是这个建议是不正确的。这是基于面向对象真实意义的一个误解。

分析:

  • 让我们从封装开始讨论。如果某些东西被封装,它就不再可见。愈多东西被封装,愈少人可以看到它。而愈少人可以看到它,我们就有愈大的弹性去改变它,因为我们的改变仅仅直接影响看到改变的那些人事物。因此,愈多东西被封装,我们改变那些东西的能力也就愈大。这就是我们首先推崇封装的原因:它使我们能够改变事物而只影响有限客户

  • 现在考虑对象内的数据。愈少代码可以看到数据(也就是访问它),愈多的数据可被封装,而我们也就愈能自由地改变对象数据,例如改变成员变量的数量、类型等等。相反,愈多的函数可以访问它,数据的封装性也就愈低。

由于第二种方式并不增加 “ 能够访问 class 内的 private 成分 ” 的函数数量。所以它更好:它导致 WebBrowser class 有较大的封装性。

在这一点上有两件事情值得注意:

第一,这个论述只适用于 non-member non-friend 函数。friends 函数对 class private 成员的访问权利和 member 函数相同,因此两者对封装的冲击力道也相同。从封装的角度看,这里的选择关键并不在 member 和 non-member 函数之间,而是在 member 和 non-member non-friend 函数之间。

第二件值得注意的事情是,只因为封装性而让函数 “ 成为 class 的 non-member ”,并不意味它 “ 不可以是另一个 class 的 member ”。

在 C++ 中,比较自然的做法是让 clearBrowser 成为一个 non-member 函数并且位于 WebBrowser 所在的同一个 namespace(命名空间)内:

namespace WebBrowserStuff{
	class WebBrowser{ ... };
	void clearBrowser(WebBrowser& wb);
	...
};

namespace 可以跨越多个源码文件而 class 不能。这很重要。它保证了 class WebBrowser{ … }; 和 void clearBrowser(WebBrowser& wb); 在一个命名空间内,以便 void clearBrowser(WebBrowser& wb); 实现功能。

总结:

  • 宁可拿 non-member、non-friend 函数替换 member 函数。这样做可以增加封装性、包裹弹性(packaging flexibility)和机能扩充性。
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值