1. 缺省构造函数,赋值函数,缺省复制构造函数
ClassA a;缺省构造函数
a=b;赋值
ClassA(const ClassA& )复制构造函数
*********************************************
函数传值时将调用复制构造函数构造临时对象,并在返回时析构临时对象
*********************************************
缺省复制构造函数只是简单复制成员,所以如果是引用型成员就要小心处理了,缺省函数未必适合。
对类成员使用初始化列表比赋值节约
注意成员构造顺序是按类中定义顺序而非初始化列表顺序
缺省赋值函数与缺省复制构造函数几乎一致,但必须注意以下区别
*********************************************
缺省赋值函数可对自身赋值,需要修改原值,赋值函数可返回值
*********************************************
-------------------------------------------------------------------------------------------------
2.接口与实现
对于成员变量提供对外访问方法而非暴露成员,可省去以后修改实现带来的麻烦
一个参数的构造函数具有隐式转换
类型转换操作符不应定义多个,否则容易出现二义
=,[],()以及->必须实现为成员函数,而不能是全局操作符
注意:全局操作符重载可对第一个参数隐式转换
缺省指针和引用参数,有个小陷阱
void f( const char *= "" );// *和=必须分开写
void f( const char* = "" );
常量const的应用
临时变量作为非常量指针传递给函数非法
常量成员函数定义如下:
int langth() const {};
注意:常量成员函数定义体中,对象所有成员变量都是常量,包括this指针
不同文件中的静态数据的初始化顺序没有被明确定义
使用句柄隐藏实现
只声明一个指针句柄
class ClassA;
class ClassB
{
ClassA *m_pObjA;
定义公共接口
}
// 私有文件实现ClassA
class ClassA
{
}
这样如果改动的是ClassA,使用者就只需链接而无需重编译
-------------------------------------------------------------------------------------------------
3.继承的注意问题
继承:Is-a关系
组合:Has-a关系
注意:任何在派生类中对操作进行限制的行为通常以为着继承架构设计上的失误.
公有继承
基类公有在派生类仍公有,保护的仍保护,私有的仍私有
可隐式转换派生类指针为基类指针
私有继承(可通过组合方式替代)
基类公有和保护都变私有,基类私有不可在派生类访问
不可隐式转换派生类指针为基类指针
保护继承
基类公有和保护都变保护,
可隐式转换派生类指针为基类指针
对虚函数的继承必须保证抽象的一致性
析构函数不能定义为纯虚函数
继承时不被继承的东西
构造函数
析构函数
赋值操作符
被隐藏的函数(在派生类中定义和基类同名但参数不一致时将隐藏基类函数)
构造过程和析构过程调用虚函数将调用基类的虚函数
-------------------------------------------------------------------------------------------------
4.多重继承问题
用虚基类解决基类的多份拷贝问题
同名函数的歧义利用在最终派生类中定义给予消除
虚基类的构造发生在最外层的构造函数中,所以一定要在所有派生类的构造函数中明确初始化他
-------------------------------------------------------------------------------------------------
5.模板
对于特定名,程序中只定义一个模板类,不可重载
关键字template和类型参数必须出现在每一个定义中
如:
template <class T>
class Stack{
Stack();
}
template <class T>
Stack<T>::Stack(){
}
实例化会迭代展开,直到所有都被实例化为止
模板参数使用模板类时,需要注意两个>>之间的空格
如:
List< Set<int> > abc
模板函数
template <class T>
void swap( T&a, T&b ){
}
调用可直接调用,通过函数重载机制找到正确函数,而不需要明确指定
int x=5,y=2;
swap(x,y);
但注意,不会有隐含转换
模板类可以提供特化版本,方法是按类型重新定义个类
如:
class List<char> {
// 重新定义
}
模板函数也可以特化,也可说是重载.
-------------------------------------------------------------------------------------------------
6.重用法则
引用参数的使用需要留意空悬指针的产生
垃圾收集机制
Arena方案
通过向new后面使用括号,可以对new传递参数
如
void *operator new( size_t bytes, int nParam ){
}
Thing *p = new( nParam ) Thing;
exit()、exec()、abort()会导致静态对象被摧毁,但不摧毁自动对象
通过在析构函数中对数值进行无意义填充,有助于Bug的检测
特定于类的new和delete可被继承,并且new参数自动变为派生类大小
-------------------------------------------------------------------------------------------------
7.异常
throw抛出异常,参数可为任何类型
异常处理器中要继续抛出时,可直接throw,不带参数
异常可销毁自动变量,但对于堆对象将不会自动清除。