effective_对象的初始化细节

effective C++条款04

首先放上一段存在多义性的代码:

class point {
public:
	point() {}
	point(int xx = 0, int yy = 0):x(xx),y(yy){}
private:
	int x, y;
};
int main() {
	point p;
	system("pause");
	return 0;
}

显然编译时报错,因为创建对象p时,p不知道该调用哪一个构造函数,这是因为point(int xx = 0, int yy = 0)带默认形参,和point()在重载的时候产生了多义性。

不要混淆初始化和赋值的概念

再看一段程序:

class point {
	friend class line;
public:
	point(){}
	point(int xx, int yy):x(xx),y(yy){}
	point(const point &p) :x(p.x), y(p.y) {};
private:
	int x, y;
};


class line {
public:
	line(const point &xp1, const point &xp2);//line类(组合类)的构造函数,初始化line类对象的数据成员;形参xp1、xp2表示point类中已有的对象
	line(const line &l) :p1(l.p1), p2(l.p2), length(l.length) {};//line类(组合类)的复构函数
	double getlength() { return length; }
private:
	point p1, p2;//line类中有3个数据成员:point类的两个对象和length
	double length;
};



//line类(组合类)的构造函数的实现
line::line(const point &xp1, const point &xp2)//:p1(xp1),p2(xp2)
{
	p1 = xp1;//这些都是赋值
	p2 = xp2;//不是初始化!!!
	double x = static_cast<double>(p1.x - p2.x);
	double y = static_cast<double>(p1.y - p2.y);
	length = sqrt(x*x + y*y);
}

注意:在line类(组合类)的构造函数本体内,p1、p2都不是被初始化,而是被赋值,而length是内置类型的,不用讨论这些。C++规定,对象成员变量的初始化发生在进入构造函数本体之前。所以point类的两个对象p1、p2其实在进入line类(组合类)的构造函数本体之前就被初始化了(很简单,程序里加断点就会发现在进入line类(组合类)的构造函数本体之前,就已经调用了2次point类的默认构造函数!!!)。
这样导致一个问题:首先调用point类的默认构造函数为p1、p2设初值,然后立刻对它们赋予新值,point类的默认构造函数的一切作用就白费了,效率太低。

接下来,把line类(组合类)的构造函数进行如下修改:

line::line(const point &xp1, const point &xp2):p1(xp1),p2(xp2),length(0)
{
	double x = static_cast<double>(p1.x - p2.x);
	double y = static_cast<double>(p1.y - p2.y);
	length = sqrt(x*x + y*y);
}

显然,用了初始化列表后,再单步调试时会发现,在初始化列表中直接调用了2次point类的复构函数,完成了p1、p2的构造(初始化),这样效率就高多了。

最后一点就是,如果成员变量是const或者引用,它们一定需要初值,不能被赋值,因此必须在初始化列表中初始化。

综上所述,构造函数最好使用初始化列表,而不要在构造函数本体内使用赋值操作。而且类中的成员变量总是以其声明次序被初始化,与初始化列表中的顺序无关。

完整代码如下:

//line类包括point类的两个对象p1、p2作为数据成员,line类具有计算线段长度的功能,在line类的构造函数中实现

#include<iostream>
#include<cmath>
using namespace std;
class point {
	friend class line;
public:
	point(){}
	point(int xx, int yy):x(xx),y(yy){}
	point(const point &p) :x(p.x), y(p.y) {};
private:
	int x, y;
};


class line {
public:
	line(const point &xp1, const point &xp2);//line类(组合类)的构造函数,初始化line类对象的数据成员;形参xp1、xp2表示point类中已有的对象
	line(const line &l) :p1(l.p1), p2(l.p2), length(l.length) {};//line类(组合类)的复构函数
	double getlength() { return length; }
private:
	point p1, p2;//line类中有3个数据成员:point类的两个对象和length
	double length;
};



//line类(组合类)的构造函数的实现
line::line(const point &xp1, const point &xp2)//:p1(xp1),p2(xp2),length(0)
{
	p1 = xp1;
	p2 = xp2;
	double x = static_cast<double>(p1.x - p2.x);
	double y = static_cast<double>(p1.y - p2.y);
	length = sqrt(x*x + y*y);
}



int main() {
	point  mypoint1(1, 1), mypoint2(4, 5);//创建point类的两个对象
	line line1(mypoint1, mypoint2);//创建line类的对象
	cout << line1.getlength() << endl;
	
	system("pause");
	return 0;
}



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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值