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特化”完成实现 ★整合重 ...
随机推荐
- JS中的Function对象
Function是函数的原型,所有的函数都来源于Function,获得函数的方法有两种类型,分为动态函数和函数继承. 动态函数 创建一个Function语法: var func = new Funct ...
- JAVA Calendar详解(转)
转自:http://blog.csdn.net/zerogotosum/article/details/1671314 (在文章的最后,将会介绍Date类,如果有兴趣,可以直接翻到最后去阅读) 究竟什 ...
- JS参数使用带参数的方法
大家都知道,在JS之中,一个变量的生命周期不是以大括号为界限的,所以即使是使用在循环或判断中的变量,外部也可以使用.可如果我们在循环或变量中使用了方法,而且这个方法使用了循环中的变量,那么后面的代码是 ...
- javascript中this,call,apply详解
javascript是一门解释型的语言,与很多面向对象语言相比有着不同特性,所以不能用面向对象的原理来理解this这个关键字. 在JS中,要真正理解this倒底指向哪个对象,必须先了解JS的作用域和原 ...
- Android onSaveInstanceState()
我们知道,由于手机的内存问题,很容易造成切换activity之后上一个activity被回收的情况,虽然我们按下back按键的时候,还是能够回到上一个activity,但是此时我们并不是执行的onRe ...
- $.Event 你不知道的用法
最近在使用Bootstrap.js,一不小心趴开源码看了一下,尤其是看到tab.js var hideEvent = $.Event('hide.bs.tab', { relatedTarget: $ ...
- 初学swift笔记变量的定义(一)
swift变量的定义 1 import Foundation /* 变量的定义 变量的类型是可以不用写的 var a=10 常量的定义 let修饰 */ print(a) let b= print(b ...
- SQL Server 的 3 种连接
第一种 1. nested loop: select * from tableA inner join tableB on tableA.X = tableB.X; 它的执行过程是这样的.对于tabl ...
- nodejs学习笔记-1
nodejs入门-安装 nodejs是什么,刚接触了一段时间,我自己也说不清楚它.按我个人的简单理解,nodejs就是一个javascript的解析器,它让javascript不在局限于浏览器客户端. ...
- POJ 1182 食物链(并查集拆点)
[题目链接] http://poj.org/problem?id=1182 [题目大意] 草原上有三种物种,分别为A,B,C A吃B,B吃C,C吃A. 1 x y表示x和y是同类,2 x y表示x吃y ...