【C++】构造函数初始化列表

        在一定程度上学习过类与对象的人一定都知道。构造函数对于类来说,比亲儿子还亲,不论是洗澡还是上厕所他俩都是天天在一起的(雾)。就算你自己不给类自定义构造函数,编译器也会自己去调用默认的构造函数。那么构造函数到底是有怎样的魅力,才让类如此离开不了自己呢?

  •   创建对象时,编译器通过调用构造函数,给对象中各个成员变量一个合适的初始值
class Date
{
public:
	Date(int year, int month, int day)
	{
		//赋值
		_year = year;
		_month = month;
		_day = day;
	}
private:
	int _year;
	int _month;
	int _day;
};

        确实,构造函数这一功能非常的好啊,难怪类天天粘这它。但是只看到这里会发现一个问题,那就是某些特殊的成员变量不能初始化啊(例:const成员变量)

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

一些反应快的人就会提到了:可以在定义的时候初始化啊!

class Date
{
public:
	Date(int year, int month, int day)
	{
		//赋值
		_year = year;
		_month = month;
		_day = day;
	}
private:
	int _year;
	int _month;
	int _day;
	const int a = 10;//这是缺省值,不是初始化
};

但是,在此,我要非常遗憾地告诉你上面这种写法是缺省值,并不是预想的初始化。

那么,就没有什么办法了吗?

不不不,这时候就是初始化列表的showtime了。

初始化列表用法:
初始化列表 :以一个 冒号开始 ,接着是一个以 逗号分隔的数据成员列表 ,每个 " 成员变量 " 后面跟一个 放在括号中的初始值或表达式
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. 类中包含以下成员,必须放在初始化列表位置进行初始化:
  • 引用成员变量
  • const成员变量
  • 自定义类型成员(且该类没有默认构造函数时)
class A 
{
public:
	A(int a)
		:_a(a)
	{}
private:
	int _a;
};

class B 
{
public:
	B(int a, int ref)
		:_aobj(a)	//初始化列表
		, _ref(ref)
		, _n(10)
	{}
private:
	A _aobj; //没有默认构造函数
	int& _ref; //引用
	const int _n; // const 
};
3. 尽量使用初始化列表初始化 ,因为不管你是否使用初始化列表,对于自定义类型成员变量,一定会先使用初始化列表初始化。

如果没有在初始化列表显示初始化: 

  • 内置类型,有缺省值用缺省值,没有就用随机值
  • 自定义类型,调用默认它的默认构造函数,如果没有默认构造就报错 
class A
{
public:
	A(int a)
		:_a(a)
	{}
private:
	int _a;
};

class B
{
public:
	B()
		:_n(10)
		, _m(2)
		, _aa(11)
	{
		// _n = 10;
	}

private:
	// const成员
	const int _n;  // 声明
	int _m = 1;    // 缺省值

	A _aa;
};

 4. 成员变量在类中声明次序就是其在初始化列表中的初始化顺序,与其在初始化列表中的先后次序无关

class A 
{
public:
	A(int a)
		:_a1(a)	//_a1初始化为1
		, _a2(_a1)	//_a2定义在_a1前,所以_a2先初始化,但此时_a1并未初始化为1
					//所以_a1为随机值,_a2也就被初始化为随机值
	{}

	void Print() 
	{
		std::cout << _a1 << " " << _a2 << std::endl;//输出‘1 随机值’
	}
private:
	int _a2;	//_a2定义在_a1前
	int _a1;
};
int main() 
{
	A aa(1);
	aa.Print();
}

end

你可能感兴趣的:(c++,开发语言)