C++类中const, static, reference等类型成员的初始化

时间:2022-09-09 23:17:20

有些成员变量的数据类型比较特别,它们的初始化方式也和普通数据类型的成员变量有所不同。这些特殊的类型的成员变量包括:

a. 常量型成员变量(const)

b. 引用型成员变量 (&)

c. 静态成员变量 (static)

d. 整型静态常量成员变量 static const int

e. 非整型静态常量成员变量 static const double

1. 常量型成员初始化:只能在构造函数的初始化列表中进行直接初始化。

如:

class Test {
public:
const  int MY_MASK;
Test() : MY_MASK( 0xff) {}
};

 

如果不是在初始化列表中对 const 常量进行初始化,而是在构造函数中对其赋值的话,是不能成功的。很简单的道理:不能给 const 成员赋值。 同样的道理,如果要初始化一个引用类型的成员变量,也不能在构造函数体内赋值,而只能在构造函数的初始化列表中进行初始化。

 

2. 引用型变量的初始化:也必须在构造函数的初始化列表中。

而所有的运算符操作都被视为赋值而不是初始化,所以引用参数的初始化必须在初始化列表中进行。

class Test{
public:
Test( int val) : ref_(val){}
~Test() {}
private:
int & ref_;};
int main(){
Test t( 1);
int a= 1;
Test t2(a);
return  0;
}

 

3. 静态成员的初始化:

类中的static变量是属于类的,不属于某个对象,它在整个程序的运行过程中只有一个副本,因此不能在定义对象时 对变量进行初始化,就是不能用构造函数进行初始化,其正确的初始化方法是:

数据类型 类名::静态数据成员名=值;

class Test{
public:
static  int MASK; // 声明int 型的MASK 常量
};
int Test::MASK= 0xFFFF; // 定义

 

这表明:

(1)、初始化在类体外进行,而前面不加static,以免与一般静态变量或对象相混淆

(2)、初始化时不加该成员的访问权限控制符private、public等

(3)、初始化时使用作用域运算符来表明它所属的类,因此,静态数据成员是类的成员而不是对象的成员。

4. 静态常量成员初始化

初始化 static const 成员,也就是全局的静态常量,和常量成员的初始化化类似,在类内声明,在类外定义。比如:

class Test{
public:
static  const  int MASK; //  申明int 型的MASK 常量,
};
const  int Test::MASK =  0xFFFF; //  定义Test::MASK 常量,注意这里不需要static 关键字

但是对于整型静态常量成员与非整型的还是有差别的,这个其实是和编译器相关的。

比如:

class Test{
public:
     static  const  int i1= 3;
     const  static  int i2= 4;
     static  const  double a1= 3.3;
     const  static  double a2= 5.7;
};

使用gcc编译器时,上面的写法是没问题的。但是在VS2008下进行编译的报错:

C++类中const, static, reference等类型成员的初始化

改成下面的方式就问题了:

class Test{
public:
     static  const  int i1= 3;
     const  static  int i2= 4;
     static  const  double a1;
     const  static  double a2;
};
const  double Test::a1= 3.3;
const  double Test::a2= 5.7;

 

注意:在const成员函数中,可以修改static成员变量的值。普通成员变量的值,是不能修改的。

一个完整的例子如下(带有注释):

#include <iostream>
using  namespace std;
class BClass {
     public:
    BClass() : i( 1), ci( 2), ri(i)  //  对于常量型成员变量和引用型成员变量,必须通过参数化列表的方式进行初始化。在构造函数体内进行赋值的方式,是行不通的。
    { }  

     void print_values() {
        cout <<  " i =\t " << i << endl;
        cout <<  " ci =\t " << ci << endl;
        cout <<  " ri =\t " << ri << endl;
        cout <<  " si =\t " << si << endl;
        cout <<  " csi =\t " << csi << endl;
        cout <<  " csi2 =\t " << csi2 << endl;
        cout <<  " csd =\t " << csd << endl;
    }
     private:
     int i;  //  普通成员变量
     const  int ci;  //  常量成员变量
     int &ri;  //  引用成员变量
     static  int si;  //  静态成员变量
    
// static int si2 = 100;  //  error: 只有静态常量成员变量,才可以这样初始化
     static  const  int csi;  //  静态常量成员变量
     static  const  int csi2 =  100//  静态常量成员变量的初始化(Integral type) (1)
     static  const  double csd;  //  静态常量成员变量(non-Integral type)
    
// static const double csd2 = 99.9;  //  error: 只有静态常量整型数据成员才可以在类中初始化(和编译器相关)

};
//  静态成员变量的初始化(Integral type)
int BClass::si =  0;
//  静态常量成员变量的初始化(Integral type)
const  int BClass::csi =  1;
//  静态常量成员变量的初始化(non-Integral type)
const  double BClass::csd =  99.9;
//  在初始化(1)中的csi2时,根据Stanley B. Lippman的说法下面这行是必须的。
//  但在VC2003中如果有下面一行将会产生错误,而在VC2005/gcc中,下面这行则可有可无,这个和编译器有关。
const  int BClass::csi2;

int main( void)
{
    BClass b_class;
    b_class.print_values();
     return  0;
}