2012-03-23
1、用const取代宏定义常量,用inline取代宏定义表达式
#define不被视为语言的一部分,比如#defina A 30 则编译器不会识别A,A不会进入符号表,而是被预处理器移走了。当程序出问题时编译器不会报错A出错
为了避免歧义,用inline取代define定义表达式
2、在类中声明定义一个常量,比如SIZE,并在类中实现int a[SIZE];
法一,用static const声明,如static onst int SIZE =5;
法二,使用枚举充当整数,如enum {SIZE=5};
注意,当使用法一时,只是SIZE的声明,必须在程序文件中定义,如下
const int MyClass::SIZE;
2012-03-26
1、处理内存不足时(比如分配不到新内存)
当new无法满足需求时,会在抛出exception之前调用一个错误处理函数
头文件<new>指定函数 set_new_handler(),传入一个函数指针
示例:void noMemory() //自己定义
{ cerr<<”无法分配内存”<<endl;
abort(); //停机
}
int main()
{ set_new_handler(noMemory);
int *p=new int [100000];
}//若无法new,则noMemory会被调用,发出一条错误信息并不正常结束
2、处理复制构造函数与赋值运算符的情况,若涉及指针,则
法一,定义自己的复制构造函数与赋值运算符重载,实现深复制
法二,将复制构造函数与赋值运算符声明为private并不要实现(阻止用户使用)
前提:相信用户不会执行赋值或复制操作时
比如针对数组的operator=,就可以设置为private,因为数组直接赋值无意义
注:静态类成员不应该在类构造函数中初始化
解释:static members在整个程序的执行过程中只应该初始化一次,若放到构造函数中,每生成一个对象便要初始化一次
3、让基类拥有virtual destructor
例:Base *p=new Derivec;
当delete p时只调用了Base的析构函数,不会调用derived的析构函数,会出错
所以,基类析构函数应该加virtual
出错场合举例:通过静态变量记录类一共产生了多少对象
class Base { Base(){num++;} ~Base(){num--;} private:static int num; }; int Base::num=0;//静态成员变量在此处初始化 |
class Derived { }//类同base int Derived::num2=0; |
当Base *p=new Derived时,num,num2都加1,但当delete p时,子类的计数不会减少
加入virtual后,析构从derived→base,所以会正确减少
4、另operator=传回一个代表某class object的reference(不需要返回const)
方便形如a=b=c=d这样的赋值
不需要返回const原因:传回const的本意是要阻止形如(a=b)=c的形式,但内建型,如int,就支持(a=b)=c,虽无使用价值,但也应遵守
但以下两种情况区别很大
string &operator=(const string&r) { return *this; } |
string &operator=(const string&r) { return r;. } |
首先,return r无法编译,因为r是const string引用,返回是string引用,类型不符
若把右侧参数改为string &r 也不对,因为形如x=”hello”;这样的语句,hello是char数组,不是string,所以编译器会通过构造函数产生一个临时string对象:
等价于:const string temp(“hello”);
x=temp;//此处的const类型是由编译器决定的,所以右侧依然不对
综上,只能用左侧形式