首先理解创建对象与调用构造函数的过程。调用构造函数时,对象将在括号中的代码执行之前被创建。也就是说先创建出对象,然后再进入构造函数的花括号执行语句。
假设有一个Queue类
Class Queue
{
private:
struct Node{Item iten; struct Node * next};
Node *front;
Node * rear;
int items;
const int qsize;
.....
public:
.....
};
假设此时他的构造函数为:
Queue::Queue(int qs)
{
front = rear = NULL;
items = 0;
qsize = qs;
}
这样的情况下,这个构造函数是无法通过编译的,因为数据成员含有const。
借用文中第一句话,我们可以知道,调用Queue(int qs)构造函数将导致程序首先给4个成员变量分配内存,然后流程执行进入花括号内,使用常规的赋值方式将值存储到内存中。因此,对于const数据成员,必须在执行到构造函数体之前,即创建对象时进行初始化。
C++提供了一种特殊的语法完成这种工作——成员初始化列表,如下所示
Queue::Queue (int qs) : qsize(qs) //initialize qsize to qs
{
front = rear = NULL;
items = 0;
}
这样写构造函数,对于出现的const int qsize 会在创建对象时同时被赋值;
然而这种方法并不限于初始化常量,可以将Queue的构造函数写成如下所示:
Queue::Queue (int qs) : qsize(qs), front(NULL), rear(NULL), items(0)
{
}
总结:
如果Classy是一个类,而mem1,mem2,mem3都是这个类的数据成员,则类构造函数可以使用如下的语法来初始化数据成员:
Classy::Classy (int m, int n) : mem1(n),mem2(0), mem3(m*n+2)
{
.........
}
上述代码mem1初始化为n,mem2初始化为0,mem3初始化为m*n+2。从概念上说初始化工作是在对象创建时完成的,此时还未执行括号中的任何代码。请注意以下几点:
① 这种格式只能用于构造函数
② 必须用这种格式初始化非静态const数据成员
③ 必须用这种形式初始化引用数据成员
数据成员被初始化的顺序与他们出现在类声明中的顺序相同,与初始化器中的排列顺序无关。
对于被声明为应用的变量,也是只能在被创建时进行初始化,因此,也必须使用初始化列表的方式。
拓展:
成员列表初始化使用括号的方式也可应用于常规初始化。也就是说,如下代码
int games = 198;
double talk = 2.73;
转化为
int games (198);
double talk (2.73);