ITEM3:不要对数组使用多态
因为数组中各元素内存地址与数组的起始地址的间隔是i*sizeof(一个在数组里的对象)。编译器为了建立正确遍历数组的执行代码,它必须能够确定数组中对象的大小。
由于数组成员对象到底是基类还是派生类无法确定,故操作易出现错误。
ITEM4:避免无用的缺省构造函数
对于某些对象来说,不用外部数据进行完全初始化是不合理的。如一个没有输入姓名的地址簿对象。
无缺省构造函数的三个问题:
1. 建立数组
例:
classEquipmentPiece {
public:
EquipmentPiece(int IDNumber);
...
};
EquipmentPiecebestPieces[10]; // 错误!没有正确调用EquipmentPiece 构造函数
EquipmentPiece*bestPieces = new EquipmentPiece[10]; // 错误!
解决办法:
① 数组定义时提供必要参数。这种方法不能用在堆数组(heap arrays)的定义上。
int ID1, ID2,ID3, ..., ID10; //存储设备ID 号的变量
...
EquipmentPiecebestPieces[] = { // 正确, 提供了构造
EquipmentPiece(ID1), // 函数的参数
EquipmentPiece(ID2),
EquipmentPiece(ID3),
...,
EquipmentPiece(ID10)
};
② 更通用的解决方法是利用指针数组来代替一个对象数组。缺点2个,第一,必须删除数组里每个指针所指向的对象,否则内存泄露。第二,增加了内存分配量。
typedefEquipmentPiece* PEP; // PEP指针指向一个EquipmentPiece对象
PEPbestPieces[10]; // 正确, 没有调用构造函数
PEP*bestPieces = new PEP[10]; // 也正确
for (int i =0; i < 10; ++i)
bestPieces[i] = new EquipmentPiece( ID Number);
③ 为数组分配raw memory,可以避免浪费内存,使用placement new方法构造对象。必须手动调用对象的析构函数,然后调用操作符delete[]释放raw memory。
// 为大小为10的数组 分配足够的内存EquipmentPiece对象
// operatornew[] 函数
void*rawMemory = operator new[](10*sizeof(EquipmentPiece));
EquipmentPiece*bestPieces = static_cast<EquipmentPiece*>(rawMemory);
for (int i =0; i < 10; ++i)
new (&bestPieces[i]) EquipmentPiece( IDNumber );
//以与构造bestPieces对象相反的顺序解构它
for (int i =9; i >= 0; --i)
bestPieces[i].~EquipmentPiec
// deallocatethe raw memory
operatordelete[](rawMemory);
2. 因为实例化一个模板时,模板的类型参数应该提供一个缺省构造函数,故它们无法在许多基于模板(template-based)的容器类里使用。
例如标准的vector模板(生成一个类似于可扩展数组的类)对它的类型参数没有必须有缺省构造函数的要求。
3. 设计虚基类时所面临的要提供缺省构造函数还是不提供缺省构造函数的两难决策。
因为几乎所有的派生类在实例化时都必须给虚基类构造函数提供参数。这就要求所有由没有缺省构造函数的虚基类继承下来的派生类(无论有多远)都必须知道并理解提供给虚基类构造函数的参数的含义。
(待续……)