More Effective C++ 笔记——条款4

条款4:非必要不提供无参构造函数


无参构造函数(default constructor)就是不用提供任何自变量就可以调用的构造函数。

ConstructFun();          // default constructor
ConstructFun(int inPut)  // no default constructor

以针对公司仪器设计的类为例:

class EquipmentPiece {
public:
    EquipmentPiece(int IDNumber);  // 构造函数一定得传入一个变量(仪器ID)    
}

由于缺乏无参构造函数,那么使用EquipmentPiece类可能会出现三个问题。

问题一:

一般而言,我们无法为数组中的对象指定传入参数,所以几乎不可能直接产生一个 EquipmentPiece数组。

EquipmentPiece pieces[10];  // 错,无法调用构造函数,因为没有传入参数
EquipmentPiece *piece = new EquipmentPiece[10];  // 错,同上

解决方案:
使用non-heap数组,在定义数组的时候提供构造函数需要的参数。

EquipmentPiece piece[] = {
    EquipmentPiece(ID1);
    EquipmentPiece(ID2);
    ......
    EquipmentPiece(ID10);
};

还可以用 “指针数组” 替代 “对象数组”。

typedef EquipementPiece* PEF
PEF piece[10];             // 正确,没有调用构造函数
PEF *piece = new PEF[10];  // 同上

// 数组中的指针可以用来指向不同的EquipmentPiece对象
for (int i = 0; i < 10; i++) {
    piece[i] = new EquipmentPiece(ID);
}

但此方法有有两个缺点
① 首先必须记得将此数组所指向的对象删除,否则会有内存泄漏的问题;
② 其次占用的内存较大,因为需要一块内存来放指针,还需要一块内存来放对象。

如何避免过度使用内存的问题(条款8):

// 分配足够的 raw memory,operator new[] 详见条款8。
void *rawMemory = operator new[](10 * sizeof(EquipementPiece));

// 让 piece 指向此块内存
EquipementPiece *piece = static_cast<EquipementPiece*>(rawMemory);

// 利用“placement new”(条款8)在这块内存中构造 EquipementPiece对象
for (int i = 0; i < 10; i++) {
    new (&piece[i])EquipementPiece(ID);
}

问题二:

许多基于模板的类(template-based container classes)需要无参构造函数。因为对于模板来说,被实例化的类必须提供一个无参构造函数。

但在多数情况下,可以通过谨慎设计模板来杜绝对无参构造函数的需求。

问题三:

虚基类如果没有无参构造函数,那么会带来很多麻烦。因为虚基类的构造函数的参数必须由,最深层次的派生类(most derived)提供。
因此,无论子类隔了多少代,都必须了解构造函数的意义,以便给虚基类的构造函数提供参数。
这就增加了派生类设计者的工作量。

既然不提供无参构造函数会有以上的问题,那么给所有的类都加上无参构造函数不就好了?

如果按照上述说法,EquipmentPiece可以修改成如下:

class EquipmentPiece {
public:
    EquipmentPiece(int IDNumber = invalidID);  // 构造函数一定得传入一个变量(仪器ID)
    ......
private:
    static const int invalidID;  // 魔鬼数字,一个无效的ID。
}

EquipmentPiece a;  // 此时可行

对于一个追求完美的程序员来说,这样做便无法保证,对象中的所有字段都是有意义的。而且如果存在一个无效ID,那么成员函数在使用ID之前就必须检查ID是否有效。

所以最好避免这种无意义的无参构造函数的出现,虽然这样做会给类的使用带来一些限制,但却有着更积极的意义——保证类所产生的对象会被完整的、正确的初始化。

  • 0
    点赞
  • 0
    收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
©️2022 CSDN 皮肤主题:数字20 设计师:CSDN官方博客 返回首页
评论

打赏作者

大聪明404

你的鼓励将是我创作的最大动力

¥2 ¥4 ¥6 ¥10 ¥20
输入1-500的整数
余额支付 (余额:-- )
扫码支付
扫码支付:¥2
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、C币套餐、付费专栏及课程。

余额充值