今天拿着《Effective C++》和《More Effective C++》结合着看了一下,主要看了有关构造函数和析构函数的几条item,其中对缺省构造函数的感受颇深。
构造函数能初始化对象,而缺省构造函数不需利用附加的外部数据就可以初始化对象。构造对象时用缺省构造函数看起来是十分方便的,但现实世界很多对象在构造时是需要提供附加数据的。那是不是就不需要缺省构造函数了呢?答案当然是否定的。首先有一些对象初始化时是可以为空值的,例如一些行为特性与数字相仿的对象被初始化为空值或不确定的值也是合理的,还有比如链表、哈希表、图等等数据结构也可以被初始化为空容器。
除了这个原因,若没有为类提供缺省构造函数,在三种情况下可能出现问题:
一、最常遇到的问题就是建立数组时。
一般来说,没有一种办法能在建立对象数组时给构造函数传递参数。
例如对类class Person{
public:
Person(string name);
......
};
在通常情况下,不可能建立person对象数组,如Person persons[5];和Person* ppersons = new Person[5],都是错误的,因为没有正确调用构造函数。
解决这个问题的方法有使用非堆数组,使用指针数组来代替一个对象数组和使用placement new 方法。
1、非堆数组的解决方法例子如下:Person persons[] = {
Person("name1"),
Person("name2"),
.......
};
但这个方法不能用在对数组上。
2、使用指针数组的方法例子如下:
Person** ppersons[5];
for (int i = 0; i < 5; ++i)
ppersons[i] = new Person( name );//在指针数组里的每一个指针被重新赋值
不过这方法有两个缺点,第一是增加了内存分配量,即需要空间来容纳指针,第二是你必须做清理工作,删除数组里每个指针所指向的对象,否则就会发生内存泄漏。我初学C++时,在要用动态多维数组时就用过这种方法,后来发现用容器就好了,省了很多麻烦和潜在危险。
3、placement new方法还没怎么研究,而且很少听说,这里就不写了。
二、没有定义缺省构造函数所造成的第二个问题是它们无法在许多基于模板的容器类里使用。因为实例化一个模板时,模板的类型参数应该提供一个缺省构造函数,这是一个常见的要求。这个要求总是来自于模板内部,被建立的模板参数类型数组里。
要解决这个问题,只能通过仔细设计模板。例如标准的vector 模板对它的类型参数没有必须有缺省构造函数的要求,但,很多模板类没有以仔细的态度去设计……
三、第三个问题是在设计虚基类时会遇到的。不过前两种问题在我实际的编程过程中都遇到过,第三种倒还没遇到过,真的是代码写少了……
几乎所有的派生类在实例化时都必须给虚基类构造函数提供参数。这就要求所有由没有缺省构造函数的虚基类继承下来的派生类(无论有多远)都必须知道并理解提供给虚基类构造函数的参数的含义。派生类的作者是不会企盼和喜欢这种规定的。
看到了上面提到的缺少缺省构造函数带来的种种限制,似乎觉得所有的类都应该有缺省构造函数。但事实并非如此,提供无意义的缺省构造函数会影响类的工作效率。首先是需要写更多的代码,这会使可执行文件或库变得更大。另外如果成员函数必须测试所有的部分是否都被正确地初始化,那么这些函数的调用者就得为此付出更多的时间,而且它们也得在测试失败的地方放置代码来处理错误。
本文探讨了C++中缺省构造函数的作用及其重要性,特别是在对象数组创建、模板容器使用及虚基类设计中不可或缺的角色。同时,也提到了提供无意义缺省构造函数可能带来的负面影响。

1924

被折叠的 条评论
为什么被折叠?



