class Queue { private: //Node is a nestedstructure definition local to this c struct Node { Item item; struct Node * next; }; enum { Q_SIZE = 10 }; Node * front; //pointer to front of Queue Node * rear; //pointer to rear of Queue int items; //current number of items in Queue const int qsize; //maximum number of items in Queue ... public: ... };
Queue::Queue(int qs) { front = rear = NULL; items = 0; qsize = qs; //not acceptable }
对Queue类,上述构造函数的实现无法正常进行的原因在于qsize是常量,所以可以对它初始化,但不能给它赋值!从概念上说,调用构造函数时,对象将在括号中的代码执行前被创建。因此调用Queue(int qs)构造函数将导致程序首先给4个成员变量分配内存。然后程序流程进入到括号中,使用常规的赋值方式将值存储到内存中。因此,对于const数据成员,必须在执行到构造函数体前,即创建对象时进行初始化。C++提供了一种特殊的语法来完成上述工作——成员初始化列表(member initializer list)。因此Queue的构造函数可以写为
Queue::Queue(int qs) :qsize(qs) { front = rear = NULL; items = 0; }
只有构造函数可以使用这种初始化列表语法。通常初值可以是常量,也可以是构造函数的参数列表中的参数。所以Queue的构造函数也可以写成
Queue::Queue(int qs) :qsize(qs), front(NULL), rear(NULL), items(0) { }
成员初始化列表的语法
从概念上讲,上述关于qsize、front、rear、item的初始化工作是在对象创建时完成的,此时还未执行括号中的任何代码。要注意:
这种格式只能用于构造函数;
必须用这种形式来初始化非静态const数据成员(至少在C++11之前是这样的);
必须用这种格式来初始化引用数据成员。这是因为引用与const数据类似,只能在被创建时进行初始化。如下
class Agent { private: Agency & belong; ... }; Agent::Agent(Agent & a) :belong(a) {...}
数据成员被初始化的顺序与他们出现在类声明中的顺序相同,与初始化器中的排列顺序无关。
C++11新增的类内初始化允许使用非静态const成员,因此Queue类的定义可写成
class Queue { private: //Node is a nestedstructure definition local to this c struct Node { Item item; struct Node * next; }; enum { Q_SIZE = 10 }; Node * front = NULL; Node * rear = NULL; int items = 0; const int qsize = Q_SIZE; ... public: ... };这与使用成员初始化列表等价。然而,使用成员初始化列表的构造函数将覆盖相应的类内初始化。