条款1 仔细区别pointers和reference
//reference 一定得代表某个对象,有初始值
string & s;//错误
string S("xy");
string& rs = s;
//没有所谓的null reference 这个事实意味着reference可能会比pointers更有效率
1.reference 不用测试其有效性 pointer需要测试它是否为空
//指针和引用之间的差异,指针可以被重新赋值,指向另一个对象。引用却总是指向它最初的对象。
string s1("xx");
string s2("yy");
string& rs = s1;
string *ps = &s1;
rs = s2; //rs仍代表S1 但是S1的值变为yy
ps = &s2; //ps指向S2 但是S1的值没有变化
结论:需要指向某个东西,而且绝不改变指向或实现操作符而其语法需求无法由指针达成,选择引用,其他选择指针。
条款2 最好使用C++转型操作符
//引入的四个新转型操作符
//static_cast const_cast dynamic_cast reinterpret_cast
过去: (type) xxxxx
现在: static_cast <type> (xx)
eg.
int a,b;
double result = ((double)a/b);
int a , b;
double result = static_cast<double>(a)/b;
//static_cast 和旧式C 强制转换具有相同的威力和限制。
//const_cast 常见用途就是去const
void update(aaa *s);
const aaaa& csw = sw;
update(&csw); //错误 update不接受
update(const_cast<aaa*>&csw); // 正确 接受。
// dynamic_cast 是向下转型 指向基类的对象引用或指针 转型为 子类的对象的引用或指针
//reinterpret_cast 转换 函数指针 类型
typedef void (*F)();
F fun[10];
//需求为将 下列函数指针放入fun中
int do();
fun[0] = & do; // 报错 类型不符
fun[0] = reinterpret_cast <F>(& do );
条款3 绝对不要以多态方式处理数组
class B{...};
class Bt:public B{...};
//内含ints
void printints(ostream& s, const B arry[],int num)
{
for(int i = 0; i< num ; ++i)
{
S<< arry[i];
}
}
//调用
B barry[10];
printints(count,barry,10); // 正确执行
Bt barry[10];
printints(cout , barry , 10); //不一定正确执行
//arry[i]是 指针算术表达式 的简写 代表 *(arry+i) arry是数组起始位置
// +i 是所指内存相距多远 i*sizeof(对象) 而参数arry申明的是B对象
//当 Bt调用时 依旧用的 B 的距离 而一般情况下 子类的大小要大于父类
条款4 非必要 不提供 默认构造(default constructor)
就是不提供默认构造函数!
条款5 对定制的 类型转换函数 保持警觉