effective c++总结,effective c++ more effective
第4章:设计和陈述
第18条:使界面易于正确使用,不易被误用。
理想情况下,如果能编译,那么接口就能达到你想要的效果,否则就编译不出来。
假设你正在设计一个表示时间数据的类的构造函数:Date(int month,int day,int year);会有两个问题。第一,传递参数的顺序不对,但是传递参数的取值范围不对。
1)用户传递参数时,顺序不对。好吧,也许你想到了使用结构,隐式转换是不允许的。如下所示:
结构日{
显式Day(int d):val(d){ }
int val};
同样,我们为月和年定义了类似的结构,这似乎解决了问题。
PS:把日、月、年放在一个完全封装的数据里,比单独定义一个结构要好。详见第22项。
日期d(1995年3月30日);//错误!错误的类型
日期d(天(30),月(3),年(1995));//错误!错误的类型
日期d(月(3),日(30),年(1995));//好的,类型是正确的
2)用户传输参数时数据范围错误。变量如何合理地表示其取值范围?例如,这里只有12个月。好的,可以这样定义:
上课月份{
公共:
静态月Jan() {返回月(1);} //返回所有有效
静态月Feb() {返回月(2);} //月份值;见下文
.//为什么是函数,不是对象,因为不能保证非局部静态变量的初始化顺序。使用此方法时,请确保所有变量都已初始化。
静态月Dec() {返回月(12);}
.//其他成员函数
私人:
显月(int m);//防止创建新的月份值
.//特定月份的数据
};
然后直接调用date d (month: mar(),day (30),year(1995));没关系。
3)尽量让你的设计类型和内置类型保持一致。避免与内置类型不合理的不兼容,其实就是提供一个行为一致的接口。
4)任何要求客户记住做某事的界面都容易出现“不正确使用”,因为客户可能会忘记这样做。比如在item13中动态分配的时候,为了避免内存泄露,我们把返回的指针给了一个唯一负责内存释放的指针。
STD:tr1:shared _ ptr Investment create Investment();
但是如果客户忘记使用智能指针怎么办?这里比较好的设计原则是主动,让它直接返回一个智能指针。这几乎完全消除了忘记释放资源的可能性。
5)如第14项所述,tr1:shard_ptr允许绑定资源释放函数,但这可能会导致“试图使用错误的资源析构函数”。比如我们要用的资源析构函数是getRidOfInvestment而不是delete。为了避免错误,我们可以返回一个tr1:shared_ptr指针,该指针将getRidOfInvestment绑定为委托者。这样,我们尝试在CreateInvestment中创建一个null tr1:shared_ptr,并使用getRidOfInvestment作为删除者。
像这样:STD:tr1:shared _ ptr investment pinv(0,getridofinvestment);
但是不能编译,因为0是int,不能转换成指针。就算能转换,也不好。这里可以通过使用强制转换来实现。所以代码变成了:
STD:tr1:shared _ ptr Investment create Investment()
STD:tr1:shared _ ptr Investment pInv(static _ cast Investment *(0),getRidOfInvestment);
pInv=.//指向正确的对象;
返回pInv
}
6)当然,如果pInv管理的原始指针可以在pInv建立之前确定,那么‘将原始指针传递给pInv构造函数’比‘将pInv初始化为null,然后重新赋值’要好。详见第26项。
7)另一个tr1:shared_ptr有一个非常好的属性:它会自动使用它的‘每个指针专用移除器’,从而消除了另一个潜在的客户错误3354‘跨dll问题’。当“一个对象在一个DLL中由new创建,但在另一个DLL中由delete销毁”时,会出现此问题。在许多平台上,这种‘跨DLL新建/删除’的配对应用会导致运行时出错。Tr1:shared_ptr可以避免这个问题,因为它的默认删除器是从“创建tr1:shared_ptr的DLL”中删除。也就是说,创建的tr1:shared_ptr可以传递给任何其他DLL,不考虑‘跨DLL问题’。这个tr1:shared_ptrs会跟踪记录,当资源的申请数变成0时,会调用绑定DLL的delete。
郑重声明:本文由网友发布,不代表盛行IT的观点,版权归原作者所有,仅为传播更多信息之目的,如有侵权请联系,我们将第一时间修改或删除,多谢。