[023]宁以non-member、non-friend替换member函数

作者在这一节中花了大幅度的篇幅来介绍为什么最好使用non-member、non-friend函数。

思路如下:

场景:如果有一个class用来表示网页浏览器,那么清楚缓存及历史记录的时候,我们可能定义下面的类:

class Web {
public:
    void clearCache();
    void clearCookies();
    void clearHistory();
}

但是也有可能用户需要一下子全部清除这些信息,于是我们再定义下面这个成员函数:

class Web {public:
    void clearEverything();
.....
}

当然,我们可以使用一个non-member函数来完成这个操作:

void clear (Web& wb) {
    wb.clearCache();
    wb.clearCookies();
    wb.clearHistory();
}

根据面向对象守则要求,数据以及操作数组的那些函数应该被捆绑在一块。虽然这么说,但是针对clear操作而言,non-member函数clear()具有更大的封装性。

因此,我们推荐使用non-member函数。

而在实际操作中,在class拥有很多操作函数的时候,我们经常是将class成为一个non-member函数并且位于web所在的同一个namespace内。比如:

 1 // 头文件“web.h”
 2 namespace Web{
 3 class Web{};
 4 .... // 放入核心机能,例如几乎客户需要的所有non-member函数
 5
 6 }
 7
 8 // 头文件“webbrowser.h”
 9 namespace Web{
10 class Web{};
11 .... // 与浏览器标签相关的函数
12
13 }
14
15 // 头文件“webcookies.h”
16 namespace Web{
17 class Web{};
18 .... // 与Cookies相关的函数
19
20 }

上述正式C++标准程序库的组织方式。

◆总结

宁以non-member、non-friend替换member函数。这样做可以增加封装性、包裹弹性和机能扩充性。

时间: 2024-10-27 08:02:17

[023]宁以non-member、non-friend替换member函数的相关文章

条款23:宁以non-member, non-friend,替换member函数。

考虑下面这种经常出现的使用方式: class webBroswer{ public: ... void clearCache(); void clearHistory(); void removeCookies(); ... }; 那么很自然的就会想到增加这么一种清理方式: class WebBrowser{ public: ... void clearEverything(); }; 或者是这么一种清理方式: void clearBrowser(WebBrowser & wb) { wb.cl

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

(一) 有个class来表示网页浏览器: class WebBrowser { public: void clearChache(); void clearHistory(); void removeCookies(); }; 许多用户会想一整个执行所有这些动作,因此WebBrowser也提供这样一个函数:clearEverything class WebBrowser { public: void clearChache(); void clearHistory(); void removeC

理解#define offsetof(struct_t,member) ((int)&((struct_t *)0)->member)

#define offsetof(struct_t,member) ((int)&((struct_t *)0)->member) 这个东西很多人应该知道: offsetof是用来判断结构体中成员的偏移位置.他是一个宏定义. (struct_t *)0是一个指向struct_t类型的指针,其指针值为 0,所以其作用就是把从地址 0 开始的存储空间映射为一个 struct_t 类型的对象.((struct_t *)0)->member 是访问类型中的成员 member,相应地 &

#define offsetof(TYPE, MEMBER) ((size_t) &((TYPE *)0)->MEMBER)

#define offsetof(TYPE, MEMBER) ((size_t) &((TYPE *)0)->MEMBER)宏的运行机理:1. ( (TYPE *)0 ) 将零转型为TYPE类型指针; 2. ((TYPE *)0)->MEMBER 访问结构中的数据成员; 3. &( ( (TYPE *)0 )->MEMBER )取出数据成员的地址; 4.(size_t)(&(((TYPE*)0)->MEMBER))结果转换类型.巧妙之处在于将0转 换成(TY

宁以non-member且non-friend替换member函数

这样做的第一个理由是增加封装性,咳咳,这听起来有点矛盾,因为non-member且non-friend成员函数要想处理某个类中的数据的话,就得看到(即能访问)该类中的数据,那么数据就得是public的.这明显破坏了封装.嗯,解释一下,不是每个函数都要明确看到数据才能处理,它可以调用类中的一序列public函数来完成任务,这些public函数可以明确地看到类中的数据,如果我们把调用他们的函数作为member函数的话,那么可以明确看到类中数据的函数的数量就会增加1,而把它作为一个non-member

读书笔记_Effective_C++_条款二十三:宁以non-member、non-friend替换member函数

有下面一种情况 class A { private: int a; int b; public: A(int x, int y) :a(x), b(y){} void a_display(){ cout << a << endl; } void b_display(){ cout << b << endl; } }; 你想输出全部的时候 member函数情况 void display(){cout<<a<<b<<endl;

Effective C++ 条款23 宁以non-member,non-friend替换member函数

1. 面向对象的真实意义并非是数据以及操作数据的函数应该被捆绑在一起,而是要求数据应该尽可能地被封装.封装意味着数据的不可见,越多的东西被封装,用户对其直接的接触就越少,用户代码和被封装内容的编译相关度就越低,"包裹弹性"就越高,也就是说,封装性越好,对代码的更改所造成的影响就越低. 2. non-member-non-friend函数实际上比public-member和friend函数要高,因为前者无法访问类的private对象,而后者可以访问类的任何对象,这显然降低了数据的封装性(

jquery 替换元素函数

1.replaceWith()使用括号内的内容替换所选择的内容.$("#div").replaceWith("<div id="div2">div2</div>");使用方法如上,将ID为div的元素替换为ID为div2的DIV元素. 2.replaceAll()将选择的内容替换到括号内的选择器.$("<div>替换后的内容</div>").replaceAll("p&

在反射中Member{get{..}set{..}}与Member{get;set;}的区别?

最近的在写代码的时候,需要用到反射来获取类中的所有公开属性值,于是写下如下代码: StringBuilder sb = new StringBuilder(); foreach (var f in this.GetType().GetFields()) { sb.AppendLine(string.Format( "{0}={1};", f.Name, f.GetValue(this))); } return sb.ToString(); 工作正常,后又在另一处对另外一个类需要获取属性