前言
本系列笔记在学习裘宗燕的中文译本-------C++程序设计特别版过程中总结出来的比较好技巧。
基础技术
引用&
引用是某一个对象的别名,必须对引用做初始化。引用的效果跟指针一样,但是安全的。
可以用 extern X& x 在其他地方初始化。
引用的值在初始化后就不能改变,因此可以作为一个常量指针的。引用初始化需要是左值。
EX:
double &d = 1;
//错误的
但是常量引用
const T& 的初始化不必是左值,甚至可以不是类型T
[1] 需要进行 到
T的隐式转换
[2] 将转换结果存储到一个
T临时变量中
[3] 用该临时变量做初始化
要区分常量引用和对变量的引用
对变量的引用,引进临时变量,极容易出错误。
常量引用,不会出现这种情况,因此常量引用作为参数是很经常的。
Ex:
const double& d = 1 ;
<=> double temp = double(1); //
首先建立一个临时对象
const double& d = temp;
//
该临时变量将一直存在,直到这个引用的作用域结束
一般临时对象
作为求值表达式,在该完整表达式的最后销毁。
指向void* 指针
一个任何对象类型的指针,可以给void* 指针赋值。但是反之不然。
但是 void*指针,不知道所指向的变量的类型,因此对void*指针做增量运算是错误的,void* 指针的用法是传递参数。
显式类型转换
(X)x
到类型X
的转换 <=>
static_cast<X>(x)
reinterpret_cast<X>(x) //
进行不相关类型之间的转换,很容易出错,除非是有保证的转换。
const_cast<X>(x)
清除const
和volatile
限定符的转换
dynamic_cast<X>(x)
运行中检查转换
函数重载
函数重载的机制:对同一个函数,实现多种功能的操作就是重载。
函数重载解除歧义的机制:参数个数、参数类型
重载匹配规则:
[1] 准确匹配
[2] 利用提升的匹配
[3] 利用标准转换
[4] 利用用户定义的转换匹配
[5] 利用参数后的省略…匹配
当这些规则后,注意歧义的出现。
重载的一些注意事项:
[1] 重载解析不考虑 函数返回
[2] 重载一会超越作用域,如果超越作用域的时候,可能出现作用域的屏蔽问题。
手工的歧义性解析
Ex:
void f1(char )
void f1(long)
int i = 0;
f1(1) ?f1(char) or f1(long)
做手工的歧义解析 inline void f1(int){ return fl(long(n));}
默认参数
void print(int value,int base = 10)
inline void print(int value){ return print(value,10); }
指向函数的指针
对一个函数只能做两件事情:调用 或者取到它的地址。
一个函数名称 相当于这个函数的地址。
void error(string s)
void (*efct)(string s) //
声明一个函数指针变量
efct = &error
ó efct = error
通过函数指针去调用函数也必须满足函数解析规则
typedef void (*SIG_TYPE)(int) //
声明一个函数指针类型
宏
#define 通过替换
可能有用的宏
#define CASE break;case
#define FOREVER for(;;)
完全没有必要的宏
#define beg {
#define end }
危险的宏
#define SQUARE(x) x*x
宏是简单替换的,所以很容易出现错误
#define INCR_XX (xx)++
拼接两个串成为一个串
#define NAME2(a,b) a##b
条件编译
#ifdef arg_two //arg_two
经过#define
Do
#endif
#if
#else
#endif
类
对私有成员的保护依靠是对于使用类成员名字的限制
但是通过地址操作和显式转换可以绕过这些限制。
构造、析构
构造函数,在创建对象的时候自动调用。
析构函数,在销毁对象的时候调用。
自引用, 可以对该对象实现多次操作。
物理的和逻辑的常量性
—— this 指针,跟非静态成员函数的属性、对象的属性有关。
如果是const非静态成员函数,则this指针是具有const属性
如果类是const 则this指针是具有const
——
在非静态
const
成员函数中修改类的属性技术
通过
const_cast<>(this) 去掉const属性
通过将变量 用
mutable
修饰
利用支持缓存技术,可以推广到各种延迟求值:将要修改的成员放在一个独立的结构中,在类声明该结构体类型的指针,利用间接访问技术。
构造、析构
[1]命名的自动对象,当程序的执行每次遇到它的声明时建立,离开它所出现的作用块时销毁。
[2]自由存储对象,通过new建立,delete销毁
[3]非静态成员对象,作为另一个对象的成员,与该对象的生命周期一样。
[4]全局对象、名字空间的对象、类的静态对象,在“程序的开始”建立一次,在程序终止时候销毁一次。
[5]临时对象,作为表达式求值的一部分被建立,在它出现的那个完整表达式的最后被销毁。
如果
临时对象做函数调用的参数,完整表达式应该是在函数调用之前
[6] 一个union成员没有构造函数、析构函数
复制构造函数、初始化、赋值
[1] 复制构造函数用于:对象的初始化、函数参数传递、函数值返回、异常。
复制构造函数的声明格式
Class X
{
//……
X(const X&); //
不然会出现递归调用
}
[2] 初始化,是对象声明的时候,进行的操作。
[3] 赋值是 (不是在声明时)对象 = 对象
[4] const
成员,成员引用
必须初始化
临时对象
[1] 临时对象,在其出现的完整表达式的最后被销毁。
[2] 临时对象,可以作为const引用,和命名对象的初始化。
[3] 在const引用 表达式中出现的临时对象,在其const引用退出作用块中才被销毁。