1.初始化列表概述
初始化列表:以一个冒号开始,接着是一个以逗号分隔的数据成员列表,每个"成员变量"后面跟一个放在括号中的初始值或表达式。
2.为什么使用初始化列表
在创建对象时,编译器通过调用构造函数,给对象中各个成员变量一个合适的初始值
比如:
class SS
{
public:SS(int c = 0){_c = c;}
private:int _c;};class S
{
public:S(int a = 0,int b=0){_a = a;_b = b;}
private:int _a;int _b;//const int _f;SS _d;
};
int main()
{S s1;return 0;
}
如果在定义使使用的是内置类型,则内置类型需要调用默认构造函数,如果是自定义类型,则需调用自定义类型的默认构造函数,如果调用自定义类型的默认构造函数,虽然调用了,但是默认构造函数的初始化只是赋初值,并不是初始化。上述构造函数调用之后,对象中已经有了一个初始值,但是不能将其称为对对象中成员变量的初始化,构造函数体中的语句只能将其称为赋初值,而不能称作初始化。因为初始化只能初始化一次,而构造函数体内可以多次赋值。
【注意】
1. 每个成员变量在初始化列表中只能出现一次(初始化只能初始化一次)
2. 类中包含以下成员,必须放在初始化列表位置进行初始化:
- 引用成员变量
- const成员变量
- 自定义类型成员(且该类没有默认构造函数时)
const修饰的类型和引用成员变量必须使用成员变量,因为这两个成员在定义的时候必须初始化,所以一定要使用初始化列表,不能用其他的
比如这样
如果不使用初始化列表,则系统会出问题。
然后来看自定义类型的初始化
class SS
{
public:SS(int c,int k,int h){_c = c;_h = h;_k = h;}
private:int _c;int _h;int _k;};
class S
{
public:S(int a = 0, int b = 0, int d = 0, int j = 0,int f=0,int k=0):_a(a), _b(b),_d(j,f,k){;}
private:int _a;int _b;SS _d;
};
int main()
{S s1;return 0;
}
注意:尽量使用初始化列表初始化,因为不管你是否使用初始化列表,对于自定义类型成员变量,一定会先使用初始化列表初始化。
注意:成员变量在类中声明次序就是其在初始化列表中的初始化顺序,与其在初始化列表中的先后次序无关
比如:
class A
{
public:A(int a):_a1(a), _a2(_a1){}void Print() {cout << _a1 << " " << _a2 << endl;}
private:int _a2;int _a1;
};
int main()
{A aa(1);aa.Print();
}
运行结果:
所以,一定要注意初始化列表的顺序,否则程序就会出现意想不到的bug。