引言
上一篇文章中介绍了构造函数,它可以在实例化一个类对象的时候自动调用,以初始化类对象:
戳我看默认成员函数详解
但是,不难发现,在构造函数体中对成员变量的初始化其实是属于对它们进行赋值操作而不是定义。那么对于一些只能在定义时给值的变量,它们在定义之后就不能改变(例如const变量与引用变量)或者一些没有默认构造函数的类类型成员变量,构造函数中无法对它们进行定义。用构造函数显然就不能满足我们的需求。
那么在类对象实例化时,这些成员变量是在哪里定义的呢?定义时又是怎么对他们进行初始化的呢?
成员变量在初始化列表中定义并初始化:
初始化列表
一般成员变量可以多次赋值,在构造函数体中进行赋值当然是可以的。但是构造函数体中只能实现赋值而不能定义成员变量,所以const成员变量、引用成员变量、无默认构造函数的类成员,就不能实现定义。而这些成员变量就必须在初始化列表中显式的定义并初始化:
class A
{
public:
A(int a)
{
_a = a;
}
private:
int _a;
};
class B
{
public:
/* B(int b)
{
_b = b;
_c = b;
} */
//错误代码: 表达式不能是常量,A不能没有默认构造函数
private:
int& _b; //引用成员变量
const int _c; //const成员变量
A _obj; //没有默认构造函数的成员类
};
定义
初始化列表是在构造函数参数列表后的,以一个冒号开始,接着是一个以逗号分隔的数据成员列表,每个"成员变量"后面跟一个放在括号中的初始值或表达式:
类名(参数列表)
: 成员变量(初始值)
, 成员变量(初始值)
, ...
{}
初始化列表是成员变量定义的地方,我们就可以在初始化列表对以上三种成员变量进行定义并初始化:
class A
{
public:
A(int a)
{
_a = a;
}
private:
int _a;
};
class B
{
public:
B(int b)
: _b(b)
, _c(b)
, _obj(b) //在初始化列表调用其构造函数
{}
private:
int& _b;
const int _c;
A _obj;
};
特性
- 每个成员变量在初始化列表中只能出现一次(初始化只能初始化一次);
- 引用成员变量、const成员变量、无默认成员函数的成员类必须放在初始化列表位置进行初始化;
- 对于自定义类型成员变量,都会先使用初始化列表进行定义并初始化(在成员变量声明是给的默认值就是在初始化列表中使用的);
- 成员变量在类中声明次序就是其在初始化列表中的初始化顺序,与其在初始化列表中的先后次序无关(所以建议将声明的次序与在初始化列表中的先后顺序写一致):
class A
{
public:
A(int a)
: _a1(a)
, _a2(a1) //错误代码:未定义标识符a1
{}
private:
int _a2;
int _a1;
};
总结
到此,关于初始化列表的内容就介绍完了
在以后的编程中,建议成员变量都在初始化列表中进行初始化。当然也存在一些需要在构造函数内赋值的情况,例如需要动态开辟空间时,初始化列表显然不适合。
如果大家认为我对某一部分没有介绍清楚或者某一部分出了问题,欢迎大家在评论区提出
如果本文对你有帮助,希望一键三连哦
希望与大家共同进步哦