C++类有几种类型的数据成员:普通类型、常量(const)、静态(static)、静态常量(static const)。这里分别探讨以下他们在C++11之前和之后的初始化方式。
在C++11之前常规的数据成员变量只能在构造函数里和初始化列表里进行初始化。const类型的成员变量只能在初始化列表里并且必须在这里进行初始化。static类型只能在类外进行初始化。static const类型除了整型数可以在类内初始化,其他的只能在类外初始化。代码如下:
class A { public: A(); ~A(); //int m_n1 = 10; // 错误 1 error C2864: “A::m_n1”: 只有静态常量整型数据成员才可以在类中初始化 int m_n2; int m_n3; //const int m_nConst_1 = 10; // 错误 3 error C2864: “A::m_nConst_1”: 只有静态常量整型数据成员才可以在类中初始化 const int m_nConst_2; const int m_nConst_3; const int m_nConst_4; // static int m_nStatic_1 = 10; // 错误 1 error C2864: “A::m_nStatic_1”: 只有静态常量整型数据成员才可以在类中初始化 static int m_nStatic_2; static int m_nStatic_3; // static double m_dStatic_1 = 10.1;// 带有类内初始化表达式的静态数据成员,必须具有不可变的常量整形类型,或必须被指定为“内联” static double m_dStatic_2; static double m_dStatic_3; static const int m_nStaticConst_1 = 10; static const int m_nStaticConst_2; const static int m_nStaticConst_3; //static const double m_dStaticConst_1 = 10; // 错误 1 error C2864: “A::m_dStaticConst_1”: 只有静态常量整型数据成员才可以在类中初始化 static const double m_dStaticConst_2; static const double m_dStaticConst_3; }; 源文件如下:
#include "Initialize.h" int A::m_nStatic_3 = 13; //类外初始化静态变量 // int A::m_nConst_4 = 13; 非静态数据成员不能在其类的外部定义 const int A::m_nStaticConst_3 = 12; // 类外初始化静态常量 A::A():m_n3(12),m_nConst_2(11),m_nConst_3(12),m_nConst_4(13)//,m_dStaticConst_2(11.0)//, m_nStaticConst_3(12)// m_nStatic_3(13)// 不是类"A"的非静态数据成员或基类 {// 错误 4 error C2758: “A::m_nConst_1”: 必须在构造函数基/成员初始值设定项列表中初始化 m_n2 = 11; // m_nConst_3 = 12; // 表达式必须是可修改的左值 // m_nStatic_2 = 12; // 无法解析外部符号 // m_dStatic_2 = 11.0; // 无法解析外部符号 // m_nStaticConst_2 = 11; // 表达式必须是可修改的左值 // m_dStaticConst_2 = 11.0; // 表达式必须是可修改的左值 } A::~A() { } 如下表:
| type | normal | const | static | static const |
|---|---|---|---|---|
| 在声明时初始化 | x | x | x | x(只有静态常量整型才可以) |
| 初始化列表初始化 | √ | √ | x | x |
| 构造函数里初始化 | √ | x | x | x |
| 类外初始化 | x | x | √ | √ |
在C++11中加入了类内初始化,常规的数据成员变量能在类内、构造函数里和初始化列表里进行初始化。const类型的成员变量只能在初始化列表里并且必须在这里进行初始化。static类型只能在类外进行初始化。static const类型除了整型数可以在类内初始化,其他的只能在类外初始化。代码如下:
class A { public: A(); ~A(); int m_n1 = 10; int m_n2; int m_n3; double m_d1 = 10.0; const int m_nConst_1 = 10; const int m_nConst_2; const int m_nConst_3; const int m_nConst_4; // static int m_nStatic_1 = 10; // 带有类内初始化表达式的静态数据成员,必须具有不可变的常量整形类型,或必须被指定为“内联” static int m_nStatic_2; static int m_nStatic_3; // static double m_dStatic_1 = 10.1;// 带有类内初始化表达式的静态数据成员,必须具有不可变的常量整形类型,或必须被指定为“内联” static double m_dStatic_2; static double m_dStatic_3; static const int m_nStaticConst_1 = 10; static const int m_nStaticConst_2; static const int m_nStaticConst_3; //static const double m_dStaticConst_1 = 10; // E1591 "const double" 类型的成员不能包含类内初始值设定项 static const double m_dStaticConst_2; static const double m_dStaticConst_3; }; 源文件代码如下:
int A::m_nStatic_3 = 13; // int A::m_nConst_4 = 13; 非静态数据成员不能在其类的外部定义 const double A::m_dStaticConst_2 = 12.0; A::A():m_n3(12),m_nConst_2(11),m_nConst_3(12),m_nConst_4(13)//, m_nStaticConst_3(12)// m_nStatic_3(13)// 不是类"A"的非静态数据成员或基类 { m_n2 = 11; // m_nConst_3 = 12; // 表达式必须是可修改的左值 // m_nStatic_2 = 12; // 无法解析外部符号 // m_dStatic_2 = 11.0; // 无法解析外部符号 // m_nStaticConst_2 = 11; // 表达式必须是可修改的左值 // m_dStaticConst_2 = 11.0; // 表达式必须是可修改的左值 } A::~A() { } 如下表:
| type | normal | const | static | static const |
|---|---|---|---|---|
| 在声明时初始化 | √ | x | x | x(只有静态常量整型才可以) |
| 初始化列表初始化 | √ | √ | x | x |
| 构造函数里初始化 | √ | x | x | x |
| 类外初始化 | x | x | √ | √ |