C++ 类和对象: 初始化列表

1. 回顾构造函数

构造函数是6个默认的成员函数之一, 完成对象初始化的工作

而在构造函数中, 有两种初始化对象的方式, 初始化列表和函数体内赋值

首先来回顾一下用函数体内赋值方法进行初始化

#include <iostream>
using namespace std;
class Date
{
public:
	Date(int year = 1, int month = 1, int day = 1)
	{
		// 函数体内赋值
		_year = year;
		_month = month;
		_day = day;
	}
	void Print()
	{
		cout << _year << "-" << _month << "-" << _day << endl;
	}
private:
	int _year;
	int _month;
	int _day;
};
int main()
{
	Date d1(1,1,1);
	d1.Print(); 
}

如图, 对对象进行了初始化

那么, 既然有了函数体内赋值初始化的方法, 为什么还需要初始化列表 ?

2. 初始化列表

这是因为有3种成员,无法在构造函数体内进行初始化

1. const修饰的成员变量

2. 引用

3. 没有默认构造函数的自定义类型成员

如下图:

那么, 这3种成员为什么无法在构造函数体内初始化? 

对于const修饰的成员变量, 引用来说, 它们必须在定义的时候进行初始化, 而初始化列表是对象成员定义的地方, 所以它们只能在初始化列表进行初始化

对于没有默认构造函数的自定义类型成员来说, 如果自定义类型成员有默认构造, 编译器会去调用它的默认构造去完成初始化, 如果没有默认构造, 编译器不知道如何对自定义类型成员进行初始化, 就报错了

因为构造函数体内是对对象整体进行初始化的, 而初始化列表是对对象成员进行初始化, 所以只能在初始化列表中手动调用有参构造对自定义类型成员进行初始化

如下例: 

#include <iostream>
using namespace std;
class testcl
{
public:
	testcl(int val)
	{
		_val = val;
	}
private:
	int _val;
};

class cl1
{
public:
	cl1(int val = 1, int ref = 1)
		// 初始化列表
		:_val(val)
		,_ref(ref)
		,t1(3)
	{
	}
private:
	const int _val = 1;
	int& _ref;
	testcl t1;
};
int main()
{
	cl1 obj1(2, 2);
}

如图, 使用初始化列表完成了对 const成员变量, 引用, 无默认构造的自定义类型完成了初始化

照上面的例子来看, 初始化列表可以做到函数体内赋值做不到的事, 那么对对象初始化只用初始化列表就可以, 为什么还需要函数体内赋值?

初始化列表只能解决大部分对象初始化的工作, 还有一些工作只能用函数体内赋值来完成, 如下例

对于返回指针的判断是无法在初始化列表中完成的, 只能在构造函数体内

 

posted @ 2023-05-10 17:01  许木101  阅读(51)  评论(0)    收藏  举报