8.7 特殊数据成员
有几类特殊的数据成员,其初始化及使用方式与前面介绍的普通数据成员有所不同,下面展开后具体讨论。
8.7.1 const数据成员
数据成员可以由const修饰,这样,一经初始化,该数据成员便具有“只读属性”,在程序中无法对其值进行修改。
事实上,在构造函数体内或复制构造函数体内初始化const数据成员是非法的,如代码8.12所示。
代码8.12 在构造函数体内无法初始化const数据成员ConstMember1
<———————————————-文件名:point.h———————————————> 01 #include<iostream> 02 using namespace std; 03 class point 04 { 05 private: 06 const int xPos;//符号常量成员xPos和yPos 07 const int yPos; 08 public: 09 point(int x,int y) 10 { 11 xPos=x;//错误,无法直接赋值 12 yPos=y; 13 } 14 point(const point&pt) 15 { 16 xPos=pt. xPos; 17 yPos=pt. yPos; 18 } 19 void print() 20 { 21 cout<<"xPos:"<<xPos<<",yPos:"<<yPos<<endl; 22 } 23 }; <———————————————-文件名:example812.cpp———————————-> 24 #include"point.h" 25 int main() 26 { 27 point pt1(3,4);//调用有参构造函数 28 pt1. print(); 29 point pt2(pt1);//调用复制构造函数 30 pt2. print(); 31 return 0; 32 }编译连接,编译器报错如下所示。 error C2758:'xPos':must be initialized in constructor base/member initializer list error C2758:'yPos':must be initialized in constructor base/member initializer list error C2166:l-value specifies const object
【代码解析】这是由于代码第11~12行造成的,const型数据成员只能通过成员初始化表达式进行初始化,所以报错。修改成如代码8.13所示。
代码8.13 使用成员初始化表达式初始化const数据成员ConstMember2
<——————————————文件名:point.h————————————————-> 01 #include<iostream> 02 using namespace std; 03 class point 04 { 05 private: 06 const int xPos; 07 const int yPos; 08 public: 09 point(int x,int y):xPos(x),yPos(y)//const数据成员只能在初始化表中初始化 10 { 11 } 12 //const数据成员只能在初始化表中进行初始化,对复制构造函数来说同样如此 13 point(const point&pt):xPos(pt. xPos),yPos(pt.yPos) 14 { 15 } 16 void print() 17 { 18 cout<<"xPos:"<<xPos<<",yPos:"<<yPos<<endl; 19 } 20 }; <——————————————文件名:example813.cpp—————————————> 21 #include"point.h" 22 int main() 23 { 24 point pt1(3,4);//调用有参构造函数 25 pt1. print(); 26 point pt2(pt1);//调用复制构造函数 27 pt2. print(); 28 return 0; 29 }
输出结果如下所示。
xPos:3,yPos:4 xPos:3,yPos:4
【代码解析】代码第9行,在成员初始化表达式中对point类的数据成员xPos和yPos进行了初始化,该操作发生在构在函数体执行之前,这样,类中的其他成员函数只能对xPos和yPos进行只读访问,无法修改其值。
如果类定义中含有const数据成员,程序员必须显式定义构造函数,使用编译器提供的默认构造函数无法完成对const成员的初始化。而缺省的复制构造函数却可以完成const成员的初始化,因此,代码8.13中定义的复制构造函数显得有些多余。
注意
在第3章曾提到,声明一个数组时,可使用诸如5、10或const等整型常量指明数组的大小,那么类中的const整型数据成员能否用于定义数据成员呢?不能,这是因为编译时,const数据成员还没有确定的值,构造函数要到程序运行以后才会被调用。