2.2 明确定义的状态
C++编程风格(修订版)
在 string 类的前两个构造函数中存在着同样的问题。
如果在创建 string 对象时调用了上述两个构造函数之一,那么这个 string 对象的初始状态将 是未定义的。在下面的代码中将输出两个字符串,其中在创建 string 对象时分别调用了上面两个 构造函数。
对 x 和 y 来说,调用函数 print() 的结果是未定义的,因为由 x.s 和 y.s 指向的字符数组中的 内容是未定义的。在这两个构造函数中,都为字符数组分配了内存,但却没有对分配的内存进行 初始化。流输出对象 cout 将持续输出字符,直到在内存中遇到第一个空字符( \0 )才停止输出。
构造函数的目的是为了初始化对象,因此一个构造函数至少应该使对象处于明确定义的状态。
构造函数应该使得对象处于明确定义的状态。
在 string 类的前两个构造函数中,对初始状态的稳妥处理就是使用空字符串,即 s[0] 应该被 设置为空。
对于这两个构造函数,我们还可以作一个改进,不过这个改进略显次要。这两个构造函数 的功能几乎是等价的:在每个构造函数中都分配了一个字符数组,并将指向数组内存的指针保存在 s 中,以及将数组的长度保存在 len 中。二者唯一的区别就是其中一个构造函数使用了默认值 来指定数组的大小,而另一个构造函数则使用参数值来指定数组的大小。除此之外,这两个函数 都是相同的。因此,我们可以有更好的选择,即使用带有默认参数值的构造函数。通过用下面的 构造函数来代替前面两个构造函数,就可以改正到目前为止所遇到的两个问题:
通常来说,用默认参数的形式来代替函数重载的形式,可以使程序更加易于维护,因为此 时程序中将只会存在一个函数体。在本示例程序中,我们对构造函数采用了函数重载的形式。对 于其他的成员函数或者非成员函数,这个规则同样适用。
考虑使用默认参数的形式来代替函数重载的形式。