EC读书笔记系列之10:条款16、17
条款18 让接口容易被正确使用,不易被误用
记住:
★“促进正确使用”的办法包括接口的一致性,以及与内置类型的行为兼容
★“阻止误用”的办法包括建立新类型、限制类型上的操作,束缚对象值,以及消除客户的资源管理责任(即类的设计者应先发制人)。
★tr1::shared_ptr支持定制型删除器。这可防范DLL问题,可被用来自动解除互斥锁等等。
--------------------------------------------------------------------------
C++的接口包括:function接口、class接口、template接口......
接口的理想情况:若客户企图使用某个接口而却没有获得他所预期的行为,应让这个代码通不过编译;若代码通过了编译,它的作为就该是客户所想要的。
a 通过导入新类型来预防接口被误用:
class Date {
public:
Date( int month, int day, int year );
...
};
客户易犯错误:
Date d( , , ); //传递参数次序错误
Date d( , , ); //传递一个无效的月份或天数
可以通过导入简单的外覆类型(即建立新类型)来解决:
struct Day {
explicit Day( int d ):val(d) {} //结构体中也可以使用成员初始化列表, //涨姿势了!!!
int val;
};
struct Month {
explicit Month( int m ):val(m) {}
int val;
};
struct Year {
explicit Year( int y ):val(y) {}
int val;
};
Date class改为:
class Date {
public:
Date( const Month &m, const Day &d, const Year &y );
...
};
使用时:
Date d( Month(), Day(), Year() );
b 通过限制对象值来预防接口被误用:
如预先定义所有有效的Months:
class Month {
public:
static Month Jan() { return Month(); } //返回有效月份
static Month Feb() { return Month(); } //同上
...
private:
explicit Month( int m ); //阻止生成新的月份,这是月份专属数据
};
使用时:
Date d( Month::Mar(), Day(), Year() );
c 通过限制类型上的操作来预防接口被误用:
如:常见的限制是加上const。
d 消除客户的资源管理责任(即类的设计者应先发制人):
对于如下语句:
Investment* createInvestment(); //此函数返回的是dumb ptrs
客户可将其返回值置入智能指针,因而将delete责任推给智能指针,但万一客户忘记就完了,此时应先发制人,就令上面函数返回一个智能指针:
std::tr1::shared_ptr<Investment> createInvestment() {
//建立一个null shared_ptr并以getRidOfInvestment为删除器
std::tr1::shared_ptr<Investment> retVal( static_cast<Investment*>(), getRidOfInvestment );
retVal = ...; //令retVal指向正确对象
return retVal;
}
shared_ptr有个好的性质是:它会自动使用它的“每个指针专属的删除器”,因而消除另一个潜在的客户错误:cross-DLL problem。这个问题发生于“对象在DLL中被new创建,却在另一个DLL内被delete销毁”。在许多平台上,这一类“跨DLL之new/delete成对运用”会导致运行期错误。shared_ptr无这个问题,∵它缺省的删除器是来自“tr1::shared_ptr诞生所在的那个DLL”的delete。
shared_ptr比原始指针大且慢,而且使用辅助动态内存。在许多应用程序中这些额外的执行成本并不显著,然而其“降低客户错误”的成效却相当显著(意指性价比很高)。
条款19 设计class犹如设计type
记住:
★class的设计就是type的设计。在定义新的type之前,请确定你已经考虑过本条款覆盖的所有讨论主题
EC读书笔记系列之10:条款16、17的更多相关文章
- EC读书笔记系列之9:条款16、17
条款16 成对使用new和delete时要采取相同形式 记住: ★若你在new表达式中使用[ ],必须在相应的delete中也使用[ ],反之亦然 -------------------------- ...
- EC读书笔记系列之8:条款13、14、15
条款13 以对象管理资源 记住: ★为防止资源泄漏,请使用RAII对象,它们在构造函数中获得资源并在析构函数中释放 ★两个常被使用的RAII classes分别是tr1::shared_ptr和aut ...
- EC读书笔记系列之16:条款35、36、37、38、39、40
条款35 考虑virtual函数以外的其他选择 记住: ★virtual函数的替代方案包括NVI手法及Strategy模式的多种形式.NVI手法自身是一个特殊形式的Template Method模式 ...
- EC读书笔记系列之5:条款9、条款10
条款9 绝不在构造和析构过程中调用virtual函数 记住: ★在构造和析构期间不要调用virtual函数,∵这类调用从不下降至derived class ---------------------- ...
- EC读书笔记系列之1:条款1、条款2、条款3
条款1:视C++为一个语言联邦 记住: ★C++高效编程守则视状况而变化,这取决于你使用C++的哪一部分 C: Object-oriented c++: Template c++: STL 条款2:尽 ...
- EC读书笔记系列之20:条款53、54、55
条款53 不要轻忽编译器的警告 记住: ★严肃对待编译器发出的警告信息.努力在你的编译器的最高(最严苛)警告级别下争取“无任何警告”的荣誉 ★不要过度依赖编译器的报警能力,∵不同的编译器对待事情的态度 ...
- EC读书笔记系列之17:条款41、42、43、44、45、46
条款41 了解隐式接口与编译器多态 记住: ★classes和templates都支持接口和多态 ★对classes而言接口是显式的(explicit),以函数签名为中心.多态则是通过virtual函 ...
- 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特化”完成实现 ★整合重 ...
随机推荐
- Mule与其它web应用服务器的区别
跟JBoss.Tomcat或其它web应用服务器相比,Mule有何不同?虽然他们有一些重要的相同点,不同点可以归结为你想达到的目标是什么.某些种类的应用对于Mule来说比较容易去编写.部署和管理,其它 ...
- Matlab自己定义函数
Matlab提供了强大的函数库供用户调用,但也支持用户自定义函数.本文使用了范德堡大学教授Akos Ledeczi授课中的样例来一步步说明怎样在Matlab中自定义函数. 首先,在command wi ...
- 【斐波拉契+数论+同余】【ZOJ3707】Calculate Prime S
题目大意: S[n] 表示 集合{1,2,3,4,5.......n} 不存在连续元素的子集个数 Prime S 表示S[n]与之前的所有S[i]互质; 问 找到大于第K个PrimeS 能整除X 的第 ...
- 集合框架-TreeSet
TreeSet是Set集合的常见子类. TreeSet:底层结构是 二叉树 元素是有排序的,但是不可以有重复元素. 相关代码演练: /* TreeSet ;元素是有序的,但是不可以元素重复. */ i ...
- zTouch-移动端触屏开发利器(zepto touch扩展)
* Zepto.js v1.0.1 touch extend (Zepto.js v1.0.1 的swipe touch扩展)js-处理手机移动端web触屏手势动作. Zepto.js v1.0.1版 ...
- FMDatabase 数据库的使用
创建,插入,更新和删除:使用executeUpdate方法,而查询则用executeQuery 1.实例化FMDatabase //paths: ios下Document路径,Document为ios ...
- Python的基础--对象
对象(Objects)是python中数据的抽象,python中所有的数据均可以用对象或者是对象之间的关系来表示.每个对象均有标识符(identity).类型(type).值(value). 标识符. ...
- python函数与方法装饰器
之前用python简单写了一下斐波那契数列的递归实现(如下),发现运行速度很慢. def fib_direct(n): assert n > 0, 'invalid n' if n < 3 ...
- EditPlus 快速去重
- php遍历目录输出目录及其下的所有图片文件
在做网站的时候,需要给文章内所有的图片添加上logo,如何利用ThinkPHP来实现. ThinkPHP为我们很好的提供了图像处理类,给文章中的所有图片加上水印的思路,上传的图片文件都保存在一个文件夹 ...