昨晚睡前看的,果然睡前看点书这个习惯要强制性养成的。
条款18 让接口被正确使用,不要被误用
不易被误用,比如Date(1,2,1991)->Date(Day(1),Month(2),Year(1991));以函数代替对象
条款19 设计类犹如设计type
创建和销毁;
copy constructor(定义了pass by value如何实现);
合法值(影响异常的抛出处理);
是否需要配合某个继承图系(inheritance graph,virtual/non-virtual)?
类型转换?
操作符和函数如何设计?
未声明的接口?
有多一般化(如果其实是定义整个types应该定义class template)?
真的需要定义新的type吗(derived class/non-member function可以代替吗)?
条款20 Prefer pass-by-reference
pass-by-value是copy了实际实参的,pass-by-reference(编译器底层)真正传递的是指针。
(1)by-value意味着调用copy constructor/destructor,如果是derived则设计更多。会调用一系列的构造函数和析构函数,代价高。
(2)pass-by-reference避免了slicing(对象切割问题)(类型转换,derived的特性被转化为base类)
[1]内置对象、STL的第二迭代器和函数对象用pass-by-value
条款21 Don‘t try to return a reference when you must return an object
--看到reference声明式应该想想它的另一个名称是什么。
(1)函数类的local对象在函数退出前就被销毁了,reference指向被销毁的值。(无定义行为)
(2)函数内不用local用static,比如:
const Rationa&l operator * (const Rational& lhs,const Rationnal& rhs){static Rational result = lhs*rhs}
调用(a*b)==(c*d)会一直等于true,相当于调用operator==(operator*(a,b),operator*(c,d))
原因:对于static对象创建一次就不会再次创建,由于返回的是reference,*(a,b)和*(c,d)操作的是同一个全局变量result,等价于==(result,result)
条款22 Declare data members priviate
(1)访问数据的一致性;就是使用方便,每次调用一定加(),第一次写C++小项目一个多项式计算器的时候,getter()、setter()有的成员有,有的没有,代码变长后/修改时每次都要回去查看,麻烦。
(2)封装,通过函数访问,日后即使修改这个成员变量,客户也不知道class内部实现已经变了,神不知鬼不觉。
[*]函数是运行时计算,成员变量是编译时确定。内存吃紧时用函数,要求速度时用成员变量(类似刷题:时间和空间上的权衡)
[*]封装性与代码破坏量成反比。取消public member,所有使用它的客户代码会被破坏;取消protected成员变量,derived class杯破坏
条款23 prefer non-member non-friend functions to member functions
条款24 Declare non-member functions when type conversions should apply to all parameters
只有当参数列于参数表内才可以参加隐式转换。
如果是class A{ 分子a,分母b;opeartor *(const A& c){return a*c.a+b*c.b;} }
result = var * 2 // 相当于var.operator*(2) 参数2杯转化为var的类型
result = 2 * var // error : 2.operator*(var) int类型没有operator
将operator(cosnt A& a,cosnt A& b){} 即可
条款25 consider support for a non-throwing swap 这个没仔细看