(一)

有个class来表示网页浏览器:

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

很多用户会想一整个运行全部这些动作,因此WebBrowser也提供这样一个函数:clearEverything

class WebBrowser {
public:
void clearChache();
void clearHistory();
void removeCookies();
void clearEverything();
};

当然也能够由一个non-member函数调用适当的member函数而提供出来:

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

那么哪一个比較好呢?是member函数clearEverything()还是non-member函数claseBrower呢。

?

越多东西被封装,我们改变那些东西的能力也就越大。对象内的数据。越少代码看到它(訪问它),越多的数据可被封装,也就越能自由地改变对象数据,比如改变成员变量的数量。类型等等。

所以答案当然是non-member函数claseBrower。由于它导致了较大的封装性。由于它并不添加“能过訪问class内之private成分”的函数数量。这就解释了为什么clearBrowser(一个non_member non-friend函数)比clearEverything(一个member函数)更受欢迎的原因:它导致WebBrowser class有较大的封装性。

可是这里有两件事情要注意下:

第一:这里仅仅适用于non-member non-friend函数。

friend函数对class private成员的訪问权力和member函数同样,因此两者对封装的冲击也同样。
第二:仅仅因在意封装而让函数“成为class 的non-member”,并不意味着它“不能够是还有一个class的member”。假如我们能够另clearBrowser成为某工具类(utility class)的一个static member函数。

(二)

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

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

像clearBrowser这种函数是个“提供便利的函数”。一个像WebBrowser这种class可能拥有大量的便利函数,某些与书签有关,某些与打印有关。某些与cookie的管理有关…,通常,大多数客户仅仅对当中某些感兴趣。

没有道理一个仅仅对书签感兴趣的客户却与一个cookie相关便利函数发生编译相依关系。

分离他们最直接的方法是将他们放入不同的头文件:

//头文件webbrowser.h这一头文件针对class WebBrowser自身以及WebBrowser核心机能。

namespace WebBrowserStuff{
void clearBrowser(WebBrowser wb);
...//WebBrowser核心机能,差点儿全部客户都须要的non-member函数。 } //头文件“webbrowserbookmarks.h” namespace WebBrowserStuff{
class WebBrowser{...};
...//与书签相关的便利函数
} //头文件“webbrowsercookies.h” namespace WebBrowserStuff{
class WebBrowser{...};
...//与cookie相关的便利函数
}

C++标准程序库正是这种组织方式。数十个头文件,每一个头文件声明std的某些机能。

假设仅仅想使用vector不用#include <memory>;假设不想使用list也不须要#include <list>.这同意客户仅仅对他们所用的那一小部分系统形成编译相依。这种分割机能并不适合class成员函数,由于class 必须总体定义,不能被分割为片段。

namespace能够跨越多个源代码文件,而class不能。

将全部便利函数放在多个头文件里但隶属同一个命名空间,意味着客户能够轻松扩展这一组便利函数。

他们所要做的就是加入很多其它non-member non-friend函数到此命名空间内。比如:假设客户想写些与影像下载相关的便利函数。仅仅要在WebBrowserStuff命名空间内建立一个头文件。内含那些函数的声明就可以。新函数就像其它旧函数一样可用且整合为一体。这是class无法提供的还有一个性质,由于class定义对客户是不能扩展的。

请记住:

尽量用non-member non-friend函数替换member函数。能够添加封装性、包裹弹性(packaging flexibility)、和机能扩充性。

Effective C++:条款23:宁以non-member、non-friend替换member函数的更多相关文章

  1. Effective C++ -----条款23:宁以non-member、non-friend替换member函数

    宁可拿non-member non-friend函数替换member函数.这样做可以增加封装性.包裹弹性(packaging flexibility)和机能扩充性.

  2. effective c++ 条款23 perfer nonmember nonfreind function to member function

    主要的理由还是封装.nonmember nonfreind function 不能访问类private 成员变量. 这个场景是有一个类提供了一些基本功能,比如 class WebBrowser { p ...

  3. Effective C++ 条款23

    宁non-member.non-friend顶替member性能 本节介绍笔者为什么时间来实现某些功能.择非成员函数而且是非友元函数.这样做总结一句话,就是最大限度的实现类的封装性. 封装意味着不可见 ...

  4. 【23】宁以non-member、non-friend替换member函数

    1.non-member方法与member方法没有本质区别,对于编译器来说,都是non-member方法,因为member方法绑定的对象,会被编译器转化为non-member方法的第一个形参.non- ...

  5. Effective C++ -----条款36:绝不重新定义继承而来的non-virtual函数

    绝对不要重新定义继承而来的non-virtual函数.

  6. Effective C++ -----条款06:若不想使用编译器自动生成的函数,就该明确拒绝

    为驳回编译器自动提供的功能,可将相应的成员函数声明为private并且不予实现. 使用像Uncopyable这样的base class也是一种做法(即先声明一个基类,然后私有继承它).这其实有点像使用 ...

  7. Effective C++ -----条款02:尽量以const, enum, inline替换 #define

    class GamePlayer{private: static const int NumTurns = 5; int scores[NumTurns]; ...}; 万一你的编译器(错误地)不允许 ...

  8. Effective C++ 条款02:尽量以const,enum,inline替换 #define

    换一种说法就是宁可以编译器替换预处理器 举例 #define ASPECT_RATIO 1.653 记号ASPECT_RATIO也许从未被编译器看见:也许在编译起开始处理源码前它就被预处理器移走了,于 ...

  9. Effective C++ 条款六 若不想使用编译器自动生成的函数,就该明确拒绝

    class HomeForSale //防止别人拷贝方法一:将相应的成员函数声明为private并且不予实现 { public: private: HomeForSale(const HomeForS ...

随机推荐

  1. CentOS服务器安装FFmpeg指南

    CentOS服务器安装FFmpeg指南 服务器系统环境为:CentOS 6.5(final): 在服务器成功安装FFmpeg颇废了一番功夫,总结一下成功安装的过程,希望对大家有用 ^_^ : Ps:使 ...

  2. python-day6---流程控制

    # if 条件:# 子代码1# 子代码2# 子代码3 # if True:# print('ok')# print('=====?>')# print('=====?>')# print( ...

  3. 最小生成树(模板 Kruskal)

    Description 某省调查乡村交通状况,得到的统计表中列出了任意两村庄间的距离.省政府“畅通工程”的目标是使全省任何两个村庄间都可以实现公路交通(但不一定有直接的公路相连,只要能间接通过公路可达 ...

  4. C# / .NET 在类中使用Server.MapPath

    直接在类中使用 Server.MapPath 会出现错误,这是由于类中不能直接使用 System.Web.UI.Page 的非静态函数造成的.解决方法有两种: 方法一.使类继承System.Web.U ...

  5. js实现个链表吧

    存储多个元素,最常用的数据结构是数组.但是数组有个一缺点,从数组中添加或移除项的成本很高,因为需要移动元素.链表也可以存储有序的元素集合,但是和数组不同,链表中的元素在内存中不是连续放置的.每个元素存 ...

  6. mysql日常运维

    一.Linux内核和发行版本 uname -a cat /etc/issue  二.glibc的版本   /lib/libc.so.6    ---没有man函数据的动态链接库   三.MySQL的版 ...

  7. C#中使用Spire.docx操作Word文档

    使用docx一段时间之后,一些地方还是不方便,然后就尝试寻找一种更加简便的方法. 之前有尝试过使用Npoi操作word表格,但是太烦人了,随后放弃,然后发现免费版本的spire不错,并且在莫种程度上比 ...

  8. Spring Data JPA 复杂/多条件组合分页查询

    推荐视频: http://www.icoolxue.com/album/show/358 public Map<String, Object> getWeeklyBySearch(fina ...

  9. Java——线程池

    body, table{font-family: 微软雅黑; font-size: 10pt} table{border-collapse: collapse; border: solid gray; ...

  10. 玩转X-CTR100 l STM32F4 l 基础例程printf、LED、蜂鸣器、拨码开关、位带操作

    我造轮子,你造车,创客一起造起来!塔克创新资讯[塔克社区 www.xtark.cn ][塔克博客 www.cnblogs.com/xtark/ ]      本文介绍X-CTR100控制器基础板载资源 ...