`
java-mans
  • 浏览: 11421355 次
文章分类
社区版块
存档分类
最新评论

《认清C++语言》---缺省构造函数

 
阅读更多

构造函数能够初始化对象,而缺省构造函数(指没有参数的构造函数)则可以不利用任何在建立对象时的外部数据就能初始化对象。这带来正反两面的效果:正面效果是:一些行为特性与数字相仿的对象被初始化为空值或不确定值是合理的,还有例如链表、哈希表、图等数据结构也可以被初始化为空容器;反面效果是:对很多对象来说,不利用外部数据进行完全的初始化是不合理的,比如一个输入姓名的通讯录对象是没有意义的。

理想情况下,无需任何数据就可以建立对象的类可以包含缺省构造函数,而需要初始数据来建立对象的类则不能包含缺省构造函数。但实际上必须考虑更多因素。

当一个类没有缺省构造函数时,使用上会存在一些限制:

考虑下面的类:

class ASCEMessage{

public:

ASCEMessage(int id);

...

};

由于ASCEMessage没有缺省构造函数,可能遇到以下问题:

1)建立数组时,一般来说,没有一种方法能在建立对象数组时给构造函数传递参数。也就是说此时不能建立ASCEMessage对象数组:

ASCEMessage asceMessages[20]; //栈上建立,错误,没有正确调用,ASCEMessage没有默认构造函数

ASCEMessage *pasceMessages = new ASCEMessage[20]; //堆上建立,错误,同上

对于栈数组,一种解决方法是在数组定义时提供必要的参数:

int id1, id2, ..., id20; //存储短信id的变量

...

ASCEMessage asceMessages[] = { //正确,提供了构造函数的参数

ASCEMessage(id1),

ASCEMessage(id2),

ASCEMessage(id3),

...,

ASCEMessage(id20)

};

遗憾的是,这种方法不能用在堆数组的定义上。

一种更通用的解决方法是利用指针数组来代替一个对象数组:

typedef ASCEMessage* PAM; //PAM指针指向一个ASCEMessage对象

PAM messages[20]; //正确,没有调用构造函数

PAM *messages = new PEM[20]; //也正确

//在指针数组里的每一个指针重新赋值,以指向一个不同的ASCEMessage对象

for(int i=0; i<20; i++)

{

messages[i] = new ASCEMessage(idx);

}

当然,该方法存在两个缺点:一是必须删除数组里每个指针所指向的对象;二是增加了内存分配量。

2)无法在许多基于模板的容器类里使用,因为实例化一个模板时,模板的类型参数应该提供一个缺省构造函数,这个要求来自模板内部,被建立的模板参数类型数组里。如下面的数组模板类:

template<class T>

class Array

{

public:

Array(int size);

...

private:

T *data;

};

template<class T>

Array<T>::Array(int size)

{

data = new T[size]; //为每个数组元素依次调用T::T()

...

}

3)设计虚基类时:一:如果不提供缺省构造函数,则很难使用它。因为几乎所有的派生类在实例化时都必须给虚基类构造函数提供参数。这就要求所有由没有缺省构造函数的虚基类继承下来的派生类都必须知道并理解提供给虚基类构造函数的参数的含义。二:提供缺省构造函数,但优化如下:

class ASCEMessage

{

public:

ASCEMessage(int ID = UNSPECIFIED);

...

private:

static const int UNSPECIFIED; //其值代表ID值不确定

};

但这样有引入一个问题,由于不能确定ID是否有意义,在用到ID的成员函数中都必须检测ID的有效性,这大大减低了代码的效率。

分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics