当前位置 : 主页 > 编程语言 > c语言 >

构造函数-初始化列表

来源:互联网 收集:自由互联 发布时间:2023-08-25
再谈构造函数 初始化列表 我们可以在函数体内初始化,也可以在构造函数之前初始化列表初始化。 为什么会有初始化列表这个东西呢?我们可以理解对于对象来说,初始化列表是成员

再谈构造函数

初始化列表

image-20230404113533567

我们可以在函数体内初始化,也可以在构造函数之前初始化列表初始化。

image-20230404113617975

为什么会有初始化列表这个东西呢?我们可以理解对于对象来说,初始化列表是成员变量定义的地方。

class A {
public:
	A()
	:_c(1)
	{}
private:
	int _a = 1;//声明
	int _b = 2;
	//const int _c; 
	const int _c  = 1;//这时候不是初始化,给的是缺省值。 
};
int main()
{
	A aa;//这里的定义是对象整体的定义,每个成员什么时候定义?
	//必须给成员变量找一个定义的位置,不然像const类型的成员不好处理,
	return 0;
}

在成员变量中加上const成员变量之后就不能正确运行了,这是因为const变量必须在定义的位置初始化,因为const只有一次初始化的机会。有const成员变量构造函数生不成了,所以要处理const成员变量。const int _c = 1;//这时候不是初始化,给的是缺省值。 C++11之前怎么处理呢?所以必须给成员变量找一个定义的位置,不然像const类型的成员不好处理。

那成员变量中的缺省值是什么时候用的?缺省值也会在成员变量初始化列表中走。

规定:1.哪个对象调用构造函数,初始化列表是它所有成员变量定义的位置;

2.不管是否显示在初始化列表写,那么编译器每个变量都会在初始化列表定义初始化;当我们在初始化列表显示写的时候,使用初始化列表中的值。

3.有三个变量必须在初始化列表初始化:const变量int& 变量名(引用也必须在定义的地方初始化),没有默认构造的自定义类型成员。每个成员在初始化列表中只能出现一次。

下面_bb也会初始化,对于自定义类型,会去调用他的默认构造;所以我们不写在初始化列表也会去调用B的构造函数。默认构造是不传参数的,一旦构造函数要传参数就必须在初始化列表中定义。

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

最好在初始化列表里进行定义,在构造函数体内已经是赋值行为了。能用初始化列表尽量用初始化列表。

class B {
public:
	B()
	{
		cout << "B()" << endl;
	}
	B(int i)
	{
		cout << "B()" << endl;
	}
private:
	int _b = 0;
};
class A {
public:
	A()
		:_c(1)
		, _b(3)
		, _ref(_a)
		, _bb(0)
	{}
private :
	int _a;//声明
	int _b;
	const int _c; 
	int& _ref;
	B _bb;
};

不管写不写初始化列表都会走,是每个成员定义的地方;对于自定义类型,调用默认构造,如果没有默认构造就显示的定义。

下面的代码中我们也可以用A aa1 = 1;进行初始化,这是一个类型转换

class A {
public :
	A(int a) 
	:_a2(a)
	{

	}
private:
	int _a2;
	int _b1;
}
int main()
{
	A aa(1);//直接调用构造	
	A aa1 = 1;
	return 0;
}

int i = 0; double d = i这句代码发生了隐式类型转换;i不是转换给d,类型转换中间会产生一个临时变量,临时变量还具有常性,i先给临时变量,再给d,临时变量类型是double。那上面的类型转换是如何发生的呢?也是中间会产生临时变量,是A类型,用1去构造一个临时对象,临时对象再去拷贝构造aa2(编译器不优化的情况下)。

image-20230405082828599

网友评论