如果一个类没有默认构造函数那么他的使用将会有很多的限制,诸如不能使用动态数组存放其对象,以及很多的模板都将不能使用高该函数。
这样一个函数,表示某个设备,他不能提供默认构造函数,因为每个设备都必须具有一个设备ID。
class EquipmentPiece {
pulic:
EquipmentPiece(int IDNumber);
...
};
通常这样的类的对象将不能使用数组存放,因为,对于数组存放的对象可能会调用该类的默认构造函数。
EquipmentPiece bestPieces[10]; // 错误!没有正确调用
EquipmentPiece *bestPieces = new EquipmentPiece[10];
// EquipmentPiece 构造函数
对于非动态的数组,可以采用列表的方式进行初化解决,
这种方式较为复杂,因此,可以用指针数组解决:
typedef EquipmentPiece* PEP; // PEP 指针指向一个 EquipmentPiece 对象
PEP bestPieces[10]; // 正确, 没有调用构造函数
PEP *bestPieces = new PEP[10]; // 也正确
这时只需要用指针指向一个新建的对象即可。
for (int i = 0; i < 10; ++i)
stPieces[i] = new EquipmentPiece( ID Number );
但是对于这种方式必须以及释放每个对象,不能使用dlete[ ], 而且对于每个对象将会有一个指针,这将会导致内存的泄露。
其实对于这种情况可以使用new运算符的构造方式方式是进行分配对象。
// 为大小为 10 的数组 分配足够的内存
// EquipmentPiece 对象; 详细情况请参见条款 M8
// operator new[] 函数
void *rawMemory = operator new[](10*sizeof(EquipmentPiece));
// make bestPieces point to it so it can be treated as
// EquipmentPiece array
EquipmentPiece *bestPieces = static_cast<EquipmentPiece*>(rawMemory);
// onstruct the EquipmentPiece objects in the memory
for (int i = 0; i < 10; ++i)
new (&bestPieces[i]) EquipmentPiece( ID Number );
但是需要手动deconstract,即调用每个对象的析构函数。
// 以与构造 bestPieces 对象相反
// 解构它。
fo (int i = 9; i >= 0; --i)
bestPieces[i].~EquipmentPiece();
// deallocate the raw memory
operator delete[](rawMemory);
对于delete[ ],我们只能和new配对使用,因此我们不能直接调用 delete [ ] bestPieces;
如果我们尝试对这样的类强制的调用添加默认构造函数,这样将会导致类的成员函数更复杂。假设它建立一个因没有 ID 而没有意义的 EquipmentPiece 对象,那么大多数成员函数必须检测 ID 是否存在。如果不存在 ID,它们将必须指出怎么犯的错误。不过通常不明确应该怎么去做,很多代码的实现什么也没有提供:只是抛出一个异常或调用一个函数终止程序。当这种情形发生时,很难说提供缺省构造函数而放弃了一种保证机制的做法是否能提高软件的总体质量。