码迷,mamicode.com
首页 > 编程语言 > 详细

【C++ Primer 第七章】 构造函数再探、委托构造函数

时间:2018-04-22 13:05:58      阅读:332      评论:0      收藏:0      [点我收藏+]

标签:影响   出现   bsp   构造   创建   const   unsigned   要求   过程   

构造函数初始值列表

1.  构造函数的初始值有时必不可少

• 有时我们可以忽略数据成员初始化和赋值之间的差异,但并非总能这样。如果成员时const或者是引用的话,必须将其初始化。类似的,当成员属于某种类类型且该类没有定义默认构造函数时,也必须将这个成员初始化。

例如:

1 class ConstRef
2 {
3 public:
4     ConstRef(int ii);
5 private:
6     int i;
7     const int ci;
8     int &ri;
9 };

和其他常量对象或者引用一样,成员ci和ri都必须被初始化。因此,如果我们没有为它们提供构造函数初始值的话将引发错误:

1 //错误:ci和ri必须初始化
2 
3 ConstRef::ConstRef(int ii)
4 {
5 //赋值
6     i=ii;  //正确
7     ci=ii;   //错误:不能给const赋值
8     ri=i;    //错误:ri没有初始化
9 }

随着构造函数体一开始执行,初始化就完成了。我们初始化const或者引用类型的数据成员的唯一机会就是通过构造函数初始值,因此该构造函数的正确形式应该是:

ConstRef::ConstRef(int ii): i(ii),ci(ii),ri(i) {}  //正确:显式地初始化引用和const成员

如果成员时const、引用,或者属于某种未提供默认构造函数的类类型,我们必须通过构造函数初始值列表为这些成员提供初值(因为如果进行赋值操作,首先要进行一次默认初始化,这样要使用都类类型的默认构造函数)。

 

2.  成员初始化顺序

• 成员的初始化顺序与它们在类定义中的出现顺序一致:第一个成员先把初始化,然后第二个,以此类推。构造函数初始值列表中初始值的前后位置关系不会影响实际的初始化顺序。

• 一般来说,初始化的顺序没什么特别要求。不过如果一个成员是用另一个成员来初始化的,那么这两个成员的初始化顺序就很关键了。 

举个例子,考虑下面这个类:

class X
{

  int i;

  int j;

public:

  X(int val):j(val),i(j) {}    //未定义的,i在j之前被初始化

};

在此例中,从构造函数的形式上来仿佛是先用val初始化了j,然后再用j初始化i。实际上,i先把初始化,因此这个初始值的效果是试图使用未定义的j初始化i!

如果可能的话,最好用构造函数的参数作为成员的初始值,而尽量避免使用同一个对象的其他成员。这样的好处是我们可以不必考虑成员的初始化顺序。例如,X的构造函数如果写成如下的形式效果会更好:

X(int val):j(val),i(val) {}

 

3.  默认实参和构造函数

//定义默认构造函数,令其与只接受一个string实参的构造函功能相同

Sales_data() {}

等价于

Sales_data(string s=" "):bookNo(s) {}

当没有给定实参,或者给定了一个string实参时,两个版本的类创建了相同的对象。因为我们不提供实参也能调用上面含有一个参数的构造函数,所以该构造函数实际上为我们的类提供了默认构造函数。

• 如果一个构造函数为所有参数都提供了默认实参,则它实际上也定义了默认的构造函数。

委托构造函数

• C++11新标准扩展了构造函数初始值的功能,使得我们可以定义所谓的委托构造函数。一个委托构造函数使用它所属类的其他构造函数执行它自己的初始化过程,或者说它把它自己的一些(或者全部)职责给了其他构造函数。

和其他构造函数一样,一个委托构造函数也有一个成员初始值的列表和一个函数体。在委托构造函数内,成员初始值列表只有一个唯一的入口,就是类名本身。和其他成员初始值一样,类名后面紧跟圆括号括起来的参数列表,参数列表必须与类中另一个构造函数匹配。

举个例子,我们使用委托构造函数重写Sales_data类,重写后的形式如下所示:

 1 class Sales_data
 2 {
 3 public:
 4     //非委托构造函数使用对应的实参初始化成员
 5     Sales_data(string s,unsigned cnt,double price):bookNo(s),units_sold(cnt),revenue(cnt*price) {}
 6 
 7     //其余构造函数全都是委托给另一个构造函数
 8     //如果要在类的外面定义构造函数,则初始值列表在定义时写出,而不是在类内声明时写出,委托构造函数也是这样,在定义时写
 9     10     Sales_data():Sales_data(" ",0,0) {}
11     Sales_data(string s):Sales_data(s,0,0)  {}
12     Sales_data(istream &is):Sales_data()  {read(is,*this);}
13 
14     //其他成员与之前的版本一致
15 };

 

【C++ Primer 第七章】 构造函数再探、委托构造函数

标签:影响   出现   bsp   构造   创建   const   unsigned   要求   过程   

原文地址:https://www.cnblogs.com/sunbines/p/8905833.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!