类和函数: 实现
C++是高度类型化的语言, 给出合适的类和模板的定义以及合适的函数声明是整个设计中最大的一部分; 这部分做好, 类, 模板以及函数的实现就不容易出问题;
人们常常犯错的原因是不小心违反了抽象的原则: 让实现细节可以提起类和函数内部的数据; 不清楚对象生命周期; 不合理的前期优化, 滥用inline; 有些实现策略会导致源文件间的相互联结问题, 小规模范围内合适, 但在重建大系统时带来巨大成本;
条款29 避免返回内部数据的句柄
请看面向对象世界里的一幕: 对象A:"亲爱的, 永远别变心" 对象B:"别担心, 亲爱的, 我是const"; 和现实生活中一样, A会怀疑, 能相信B么? again, 和现实生活中一样, 答案取决于B的本性: 成员函数的组成结构;
e.g. 假设B是const String对象:
1
2
3
4
5
6
7
8
9
10
11
|
class
String {
public
:
String(
const
char
*value);
// 具体实现参见条款11
~String();
// 构造函数的注解参见条款 M5
operator
char
*()
const
;
// 转换String -> char*;参见条款 M5
...
private
:
char
*data;
};
//...
const
String B(
"Hello World"
);
// B 是一个const 对象
|
B是const, 最好的情况就是无论什么时候, B的值总是"Hello World"; 这就要寄希望于其他程序员以合理的方式使用B;
万一有人将B强制转换掉const; [拜拜了, 亲爱的]
1
|
String& alsoB =
const_cast
<String&>(B);
// 使得alsoB 成为B 的另一个名字 但不具有const 属性
|
即使没有人做这种残暴的事情, 还是不能保证B永远不变:
1
2
|
char
*str = B;
// 调用B.operator char*()
strcpy
(str,
"Hi Money"
);
// 修改str 指向的值
|
>B现在的值到底还是不是Hello World, 答案取决于String::operator char*的实现;
下面的实现会导致错误的结果, 虽然工作起来高效;
1
2
|
// 一个执行很快但不正确的实现
|