18.让接口容易被正确使用
问题:
class Date {
public:
Date(int month,int day, int year;
}
以上代码问题:
- 容易以错误的顺序传递参数
- 可能传递无效的月份或天数
解决方法:
- 通过导入新类型获得预防
struct Day {
explicit Day(int):val(d){}
int val;
};
class Date {
public:
Data(const Month& m, const Day& d, const Year& y);
};
Date d(Month(3), Day(30), Year(1995));
以上代码无法限制数据范围
解决方法:
class Month {
public:
static Month Jan() {return Month(1);}
static Month Feb() {return Month(2);}
private:
explicit Month(int m);
};
Date d(Month::Feb(), Day(30), Year(1995));
接口设计原则
- 接口不容易被误用
- 建立新类型
- 限制类型上的操作
- 消除客户的资源管理责任
- 接口一致性
- stl容器都有一个size接口
- 不要有的时length,有的是size
- 任何接口如果要求客户必须记得做某事,会有不正确使用倾向
Investment* createInvestment();
auto_ptr<Investment> createInvestment()
19.设计class犹如设计type
需要考虑的问题:
- 新type对象该如何创建和销毁
- 构造函数,析构函数
- operator new,operator delete, operator new[] operator delete[]
- 对象初始化和对象赋值有什么区别
- 新type的对象如果被pass by value,意味着什么?
- 什么时新type的合法值
- 新type需要配合某个继承图系吗
- 如果继承某个既有类,受到该类的影响,特别时virtual,non-virtual的影响
- 如果容许其他类继承,影响你所声明的函数,尤其时析构函数是否为virtual
- 你的type需要什么样的转换
- T1需要转换为T2,T1内写类型转换函数operator T2,或着T2内写non-explicit 构造函数
- 转换是否需要为explicit的函数
- 什么样的操作符和函数是合理的
- 该谁取用新的type的成员
- public,protected,private,friend
- 你的新type有多么一般化
20.宁以pass-by-reference-to-const替代pass-by-value
使用pass-by-value问题
- 传递的类对象执行copy构造函数,造成性能低下
- 类对象内部的成员变量执行copy构造函数,造成性能低下
解决方法:
- 传递常量引用
- 传递引用可以避免切割发生(切割后virtual函数调用的是基类的virtual函数)
- 对于内置对象,pass-by-value更高效
- 小型的类对象,pass-by-reference更高效
- 编译器可能不会对小型类对象优化
- 类对象大小随着需求增加可能会变化,会变为大的类对象