EC读书笔记系列之12:条款22、23、24
条款22 将成员变量声明为private
记住:
★切记将成员变量声明为private。这可赋予客户访问数据的一致性、可细微划分访问控制、允诺约束条件获得保证,并提供class作者以充分的实现弹性。
★protected并不比public更具封装性
条款23 宁以non-member-non-friend替换member函数
记住:
★宁可拿non-member-non-friend函数替换member函数。这样可增加封装性、包裹弹性和机能扩充性。
-------------------------------------------------------------------------------
举例:
class WebBrowser {
...
void clearCache(); //清除缓存
void clearHistory();//清除历史
void clearCookies();//清除cookies
...
};
假设想一次性执行上面三个有关清理的函数,有两种方法:
方法一:将这个一次性清理工作函数写成member function:
class WebBrowser {
public:
...
void clearEverything(); //调用上面的三个函数
...
};
方法二:写成non-member-non-friend函数:
void clearBrowser( WebBrowser &wb ) {
wb.clearCache();
wb.clearHistory();
wb.clearCookies();
}
方法二要好一点!!!因为non-member函数将导致较大的封装性,∵其并不能访问class内部的private成分。(因为对于对象内的数据来说,愈少代码可以看到数据,也即访问它,愈多的数据就可被封装,而我们也就愈能自由地改变对象的数据,这不也就是封装性的体现吗!!)
两件需要注意的事:
一、上述论述仅适用于no-member-non-friend函数;
二、因在意封装性而让函数“成为class的non-member”,并不意味着其“不可以是另一个class的member”
推荐做法:
让clearBrowser成为一个non-member并且位于WebBrowser所在的同一个namespace内:
namespace WebBrowserStuff {
class WebBrowser {...};
void clearBrowser( WebBrowser &wb );
...
} //注意namespace这里无分号!!!
注:像上面WebBrowser这样的class可能拥有多种便利函数,如某些与书签有关,某些与打印有关等。可以将这些便利函数的编译相依关系降低:分离他们的直接做法是将书签相关的便利函数声明于一个头文件,将打印相关的便利函数声明于另一个头文件:
namespace WebBrowserStuff {
class WebBrowser{...}; //核心机能
}
//头文件"webbrowserbookmark.h"
namespace WebBrowserStuff {
... //与书签相关的便利函数
}
//头文件"webbrowserprint.h"
namespace WebBrowserStuff {
... //与打印相关的便利函数
}
以此种方式切割机能并不适用于member函数,因为一个class必须整体定义,不能被分割为片段,从这个角度来说也符合本条款的主题。
条款24 若所有参数皆需类型转换,请为此采用non-member函数
记住:
★若需要为某个函数的所有参数(包括被this指针所指的那个隐喻参数)进行类型转换,那么此函数必须是个non-member。
-------------------------------------------------------------------------------
举例:有理数类
class Rational {
public:
Rational( int numerator = ,
int denominator =
); //构造函数刻意不为explicit,
//这样做是为了int-to-Rational隐式转换
...
};
现让该有理数类支持乘法运算。现将operator*写为类的member函数:
class Rational {
public:
...
const Rational operator*( const Rational &rhs ) const;
};
若下面这样用:
Rational oneEighth( , );
Rational oneHalf( , );
Rational result;
result = oneHalf*oneEighth; //用法1:可以
result = oneHalf*; //用法2:可以
result = *oneHalf; //用法3:错误
这里的用法2,之所以行得通,是因为这里发生了隐式类型转换,等价于下面这样调用:
const Rational temp(2); //建立一个暂时性的Rational对象
result = oneHalf*temp; //等价于oneHalf.operator*( temp );
当然这种做法可行的前提是non-explicit constructor!!!
仅当参数被列于参数列内,此参数才是隐式类型转换的合格参与者,这是用法2和用法3的区别。
解决方案:将operator*写成non-member函数,这样便可以使在每一个实参身上执行隐式类型转换!!!
const Rational operator*( const Rational &lhs,
const Rational &rhs
) { return Rational( lhs.numerator() * rhs.numerator(),
rhs.denominator() * rhs.denominator()
);
}
这样:
result = oneHalf*;
result = *oneHalf; //也可以通过编译了!!!
注意:
member函数的反面是non-member函数,而不是friend函数!!!(因为有太多的C++程序员错误地认为若一个“与某class相关”的函数不该成为一个member,就该是个friend)
EC读书笔记系列之12:条款22、23、24的更多相关文章
- EC读书笔记系列之7:条款12 复制对象时勿忘其每一个成分
记住: ★copying函数应确保复制“对象内的所有成员变量”及“所有base class成分” ★不要尝试以某个copying函数实现另一个copying函数.应该将共同机能放进第三个函数中,并由两 ...
- EC读书笔记系列之16:条款35、36、37、38、39、40
条款35 考虑virtual函数以外的其他选择 记住: ★virtual函数的替代方案包括NVI手法及Strategy模式的多种形式.NVI手法自身是一个特殊形式的Template Method模式 ...
- EC读书笔记系列之1:条款1、条款2、条款3
条款1:视C++为一个语言联邦 记住: ★C++高效编程守则视状况而变化,这取决于你使用C++的哪一部分 C: Object-oriented c++: Template c++: STL 条款2:尽 ...
- EC读书笔记系列之20:条款53、54、55
条款53 不要轻忽编译器的警告 记住: ★严肃对待编译器发出的警告信息.努力在你的编译器的最高(最严苛)警告级别下争取“无任何警告”的荣誉 ★不要过度依赖编译器的报警能力,∵不同的编译器对待事情的态度 ...
- EC读书笔记系列之19:条款49、50、51、52
条款49 了解new-handler的行为 记住: ★set_new_handler允许客户指定一个函数,在内存分配无法获得满足时被调用 ★Nothrow new是一个颇为局限的工具,∵其只适用于内存 ...
- EC读书笔记系列之18:条款47、48
条款47 请使用traits classes表现类型信息 记住: ★Traits classes使得“类型相关信息”在编译期可用.它们以templates和“templates特化”完成实现 ★整合重 ...
- EC读书笔记系列之17:条款41、42、43、44、45、46
条款41 了解隐式接口与编译器多态 记住: ★classes和templates都支持接口和多态 ★对classes而言接口是显式的(explicit),以函数签名为中心.多态则是通过virtual函 ...
- EC读书笔记系列之15:条款32、33、34
条款32 确保你的public继承塑模出is-a关系 记住: ★public继承意味着is-a.适用于base class身上的每一件事情一定也适用于derived class身上,∵每一个deriv ...
- EC读书笔记系列之14:条款26、27、28、29、30、31
条款26 尽可能延后变量定义式的出现时间(Lazy evaluation) 记住: ★尽可能延后变量定义式的出现.这样做可增加程序的清晰度并改善程序效率 ----------------------- ...
随机推荐
- Newton‘ method 的优缺点
watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvdTAxMzE1Mjg5NQ==/font/5a6L5L2T/fontsize/400/fill/I0JBQk ...
- .NET与你若仅仅如初见(一)
难忘初次见到你,那是一个夏日的午后,可是天空中乌云密布.大雨来临前的一段时间总是非常闷热的,当我朦胧的睡眼看到你之后瞬间就清醒了,感觉空气也凉爽了起来.尽管仅仅一眼但就是被你那清新脱俗沉鱼落雁之美所征 ...
- OC中NSString 的常用方法
NSString *str1 = @"BeiJing"; NSString *str2 = @"beijing"; //全部转为大写 NSLog(@" ...
- javascript 压缩空格代码演示
压缩空格代码演示 主要是讲解 压缩一个字符串两段空格 例如:javascript函数里的空格不论是这样 var s = "Hello World ...
- C++ vector 实现二维数组时, 在类的头文件中定义时遇到"应输入类型符"的问题?
见下,当我在类的声明文件中定义二维vector时,提示我应输入类型说明符; 但是相同的格式定义,在类中将二维vector修改为在源文件中定义就可以顺利通过,并顺利执行打印 打印结果如下: 望大神来解惑 ...
- POJ 3279(Fliptile)题解
以防万一,题目原文和链接均附在文末.那么先是题目分析: [一句话题意] 给定长宽的黑白棋棋盘摆满棋子,每次操作可以反转一个位置和其上下左右共五个位置的棋子的颜色,求要使用最少翻转次数将所有棋子反转为黑 ...
- 35个jQuery小技巧!
1. 禁止右键点击$(document).ready(function(){ $(document).bind("contextmenu",function(e){ ...
- 利用js闭包获取索引号
以tab选项卡效果为例: 网页中的选项卡效果
- Smarty3配置
下载Smarty压缩包并解压,复制其中的libs文件夹到我们的PHP工程目录下(可将其改名为smarty).同时,在工程目录下新建三个文件夹,分别取名为templates.templates_c和sm ...
- UML-类图,包图
UML构造设计模型 一.类图 二.包图 三.组件图 四.部署图 一.类图 1.类:类由三格表示:类名,类的属性,类的操作 类名: 首字母大学 ...