C++语言—深入理解构造函数

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/z_x_m_m_q/article/details/82492553

构造函数体内的赋值:

 创建一个类对象时,编译器通过调用构造函数,给对象中的成员变量一个初值

class Date
{
public:
	//构造函数体内赋值
	Date(int year,int month,int day)
	{
		_year = year;
		_month = month;
		_day = day;
	}
private:
	int _year;
	int _month;
	int _day;
};

虽然上述构造函数调用之后,对象中已经有了一个初始值,但是不能将其称作类对象成员的初始化,构造函数体中操作只能将其称作为赋初值,而不能将其称作为初始化。因为初始化只能初始化一次,而构造函数体内,可以给 成员多次赋值

初始化列表:
以一个冒号开始,接着是一个以逗号分割的数据成员列表每个"成员变量"后面跟一个放在括号中的初始值或表达式

class Date
{
public:
	//用初始化列表初始化对象成员变量
	Date(int year,int month,int day)
		:_year(year)
		,_month(month)
		,_day(day)
	{}
private:
	int _year;
	int _month;
	int _day;
};

说明:

  1. 每个成员在初始化列表中只能出现一次
  2. 初始化列表仅用于初始化类的数据成员,并不指定这些数据成员的初始化顺序,数据成员在类中定义顺序就是在初始化列表中的初始化顺序
  3. 尽量避免使用成员初始化成员,成员的初始化顺序最好和成员的定义顺序保持一致
  4. 类中包含以下成员,必须放在初始花列表中对其初始化:
  • 引用成员标量
  • const 修饰的成员变量
  • 类类型成员

构造函数作用:

构造函数不仅可以把对象构造成功,还可以给对象中各个成员变量一个初始值,有时候还具有类型转换的作用(这点以后解释)

默认构造函数: 

如果一个类未显式定义构造函数时,编译器会合成一个默认的构造函数。如果类显式定义了,编译器将不再合成。
注意:编译器合成的构造函数一定是不带参数的

class Date
{
public:
	void show()
	{
		cout << _year << "-" << _month << "-" << _day << endl;
	}
private:
	int _year;
	int _month;
	int _day;
};

void test()
{
	Date d;
	d.show();  //随机值
}

以上代码中我们没有显示定义构造函数,对象可以创建成功,因为编译器合成了一个默认的不带参数的默认构造函数,但是该默认构造函数实际什么事情都不做,类似以下方式:

Date()
{}

即该构造函数实际没有任何意义。那完全可以不用合成,合成了就要调用,而调用了该构造函数又没有实际意义, 而且还影响程序的效率

通过汇编代码发现,创建对象语句底层没有构造函数对应的汇编语句,即编译器并未合成构造函数(可以显式添加无参构造函数,就会看到调用构造函数的汇编代码)

因此编译器对是否合成构造函数进行了优化,编译器根据自己的需求选择性的合成构造函数,即如果类中没有显式定义构造函数,在编译器需要且有能力合成时,会合成一个无参的构造函数。比如

class Time
{
public:
	Time(int hour = 12,int minute = 12,int second = 12)
		:_hour(hour)
		,_minute(minute)
		,_second(second)
	{}
private:
	int _hour;
	int _minute;
	int _second;
};

class Date
{
public:
	void show()
	{
		cout << _year << "-" << _month << "-" << _day<< endl;
	}
private:
	int _year;
	int _month;
	int _day;
	Time _t;
};

void test()
{
	Date d;
	d.show();
}

Time类显式定义了其缺省的构造函数,Date类未显式定义构造函数,其中包含了一个Time类对象。当创建Date类对象时,编译器需要调用Date类的构造函数完成Date类对象的构造,由于Date未显式定义,此时编译器必须合成:因为Time类的构造函数存在,合成Date构造函数的目的就是为了完成Data类对象中包含的Time类对象的构造

但是,如果将Time类缺省的构造函数改成非缺省构造函数编译器就没有能力合成,此时会报错

这里很好的说明了编译器 有必要且有能力 合成构造函数 

猜你喜欢

转载自blog.csdn.net/z_x_m_m_q/article/details/82492553