构造函数初始化

有时我们可以忽略数据成员初始化和赋值之间的差异,但并非总能这样。如果成员是const或者是引用的话,必须将其初始化。例如:
class ConstRef{
public :
ConstRef(int ii);
private :
int i;
const int ci;
int &ri;
};
和其他常量对象或者引用一样,成员ci和ri都必须被初始化。因此,如果我们没有为他们提供构造函数初始值的话将引发错误:
//错误:ci和ri必须被初始化
ConstRef::ConstRef(int ii){
//赋值:
i = ii; //正确
ci =ii; //错误:不能给const赋值
ri =i; //错误:ri没被初始化
}
随着构造函数体一开始执行,初始化就完成了。我们初始化 const 或者引用类型的数据成员的唯一机会就是通过构造函数初始值,因此该构造函数的正确形式应该是:
//正确:显式地初始化引用和const 成员
ConstRef::ConstRef(int ii):i(ii),ci(ii),ri(i){}

如果成员是const、引用,或者属于某种未提供默认构造函数的类类型,我们必须通过构造函数初始值列表为这些成员提供初值。


建议:使用构造函数初始值
在很多类中,初始化和赋值的区别事关底层效率问题:前者直接初始化数据成员,后者则先初始化再赋值。
除了效率问题外更重要的是,一些数据成员必须被初始化,建议读者养成使用构造函数初始值的习惯,这样能避免某些意想不到的编译错误,特别是遇到有的类含有需要构造函数初始值的成员时。

·成员初始化的顺序
显然,在构造函数初始值中每个成员只能出现一次,否则,给同一个成员赋两个不同的初始值有什么意义呢?
不过让人稍感意外的是,构造函数初始值列表只说明用于初始化成员的值,而不限定初始化的具体执行顺序。
成员的初始化顺序与他们在类定义中的出现顺序一致:第一个成员先被初始化,然后第二个,以此类推。构造函数初始值列表中初始值的前后位置关系不会影响实际的初始化顺序。
一般来说,初始化的顺序没什么特别要求。不过如果一个成员使用另一个成员来初始化的,那么这两个成员的初始化顺序就很关键了。
举个例子,考虑下面这个类:

class X{
int i;
int j;
public :
X(int val):j(val),i(j){}
};

在此例中,从构造函数初始值的形式上来看仿佛是先用val初始化了j,然后再用j初始化i。实际上,i先被初始化,因此这个初始值的效果是试图使用未定义的值j初始化i!
有的编译器具备一项比较友好的功能,即当构造函数初始值列表中的数据成员顺序与这些成员声明的顺序不符时会生成一条警告信息。

·最好令构造函数初始值的顺序与成员声明的顺序保持一致。而且如果可能的话,尽量避免使用某些成员初始化其他成员。

如果可能的话,最好用构造函数的参数作为成员的初始值,而尽量避免使用同一个对象的其它成员。这样的好处是我们可以不必考虑成员的初始化顺序。例如,X的构造函数如果写成如下的形式效果会更好:
X(int val):i(val),j(val){ }
在这个版本中,i和j初始化的顺序就没什么影响了。

·默认实参和构造函数
Sales_data默认构造函数的行为与只接受一个string实参的构造函数差不多。唯一的区别是接收string实参的构造函数使用这个实参初始化bookNo,而默认构造函数(隐式地)使用string的默认构造函数初始化bookNo。我们可以把它们重写成一个使用默认实参的构造函数:

class Sales_data{
public:
//定义默认构造函数,令其与只接受一个string实参的构造函数功能相同
Sales_data(std::string s = ""):bookNo(s){}
//其他构造函数与之前一致
Sales_data(std::string s,unsigned cnt,double rev):bookNo(s),units_sold(cnt),revenue(rev*cnt){}
Sales_data(std::istream &is){read(is,*this);}
//其他成员与之前的版本一致
};

在上面这段程序中,类的接口与第237页的代码是一样的。当没有给定实参,或者给定了一个string实参时,两个版本的类创建了相同的对象。因为我们不提供实参也能调用上述的构造函数,所以该构造函数实际上为我们的类提供了默认构造函数。

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

值得注意的是,我们不应该为Sales_data接收三个实参的构造函数提供默认值。因为如果用户为售出书籍的数量提供了一个非零的值,则我们就会期望用户同时提供这些书籍的售出价格。

转载于:https://www.cnblogs.com/CharlesNels/p/9555713.html

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值