16. 类的 static const 成员

16.1. const 成员

const 数据成员的初始化只能在类的构造函数的初始化列表中进行。声明 const 变量时不能初始化。

Note

必须使用初始化列表的情形:

  • 常量成员 ,因为常量只能初始化不能赋值,所以必须放在初始化列表里面。

  • 引用类型 ,引用必须在定义的时候初始化,并且不能重新赋值,所以也要写在初始化列表里面。

  • 没有默认构造函数的 类类型 ,因为使用初始化列表不调用默认构造函数来初始化,而是直接调用拷贝构造函数初始化。

Warning

成员是按照他们在类中 声明 的顺序进行初始化的,而不是按照他们在初始化列表出现的顺序初始化的。

16.2. static 成员

不能在定义对象时对静态变量进行 定义和初始化 ,即不能用构造函数进行初始化。 初始化在类体外进行,前面不加 static 修饰。

16.3. static const 成员

静态常量成员,可以直接初始化(static const 和 const static 含义相同)。

 1/* header.h */
 2class Solution
 3{
 4public:
 5  static void print()
 6  {
 7    cout << var << endl; // 100
 8    cout << (mapping.begin()->second)[0] << endl; // 'a'
 9  }
10
11private:
12  static const map<char, vector<char>> mapping; // 常量声明式
13  static const int var = 100; // 常量声明式(直接初始化)
14};
15
16/* source.cpp */
17const map<char, vector<char> > Solution::mapping = {{'2', {'a', 'b', 'c'}},
18                                                    {'3', {'d', 'e', 'f'}},
19                                                    {'4', {'g', 'h', 'i'}}}; // mapping 的定义
20
21// 注:const map 只能通过成员函数 at 或迭代器 const_iterator 访问元素(it->first, it->second),不能通过下标[]的方式访问。
22
23// 对应类的 static const int/char/bool 成员常量,如果不取他们的地址,则可以直接声明并使用,而无需提供以下的定义式。
24const int Solution::var; // var 的定义。由于常量 var 在类内声明时已经获得了初始值,因此定义时不可以再设初始值。

Note

初始化 :变量还没有值,现在赋予它一个值。

赋值 :变量已经有一个值,现在擦除它之前的值,赋予一个新的值。

声明 :告诉编译器类型及其细节,不涉及内存分配。

定义 :编译器将在内存地址上为该对象定址,即分配内存;定义的同时也作了声明。

Warning

staticconst 不能 同时 修饰成员函数,只能修饰成员变量。 因为常量成员函数(const)拥有一个 this 指针,是一个指向常量类类型的常量指针,而静态成员函数(static)没有 this 指针。

Note

头文件中应该写什么?
  • 变量和函数的声明,而不是定义。如:extern int a; void f(); 是允许的,而 int a; void f() {}; 是不允许的。

  • const 全局变量可以定义在头文件中,不会因为头文件重复包含而导致变量重复定义的编译错误。 但是在定义指针时要注意, const char* p = "name" 定义的指针不是 const,可能导致错误;而 char* const p = "name" 不会。

  • 内联函数。

  • 类的定义。成员函数定义在类的定义体内,编译器会视其为内联函数;如果定义在类的头文件内,而没有写进类定义体内,是不合法的,需要定义 在别的源文件(.cpp)文件内。

  • 函数模板和类模板成员函数。

把声明在头文件(header.h)中的函数或类成员函数定义在一个源文件(source1.cpp)中,需要包含该头文件(#include “header.h”),当 另一个源文件(source2.cpp)需要调用上述函数时,只需要包含头文件(#include “header.h”),而不是包含函数定义的源文件(source1.cpp)。

16.4. 参考资料

  1. C++ static、const和static const类型成员变量声明以及初始化

  1. 头文件中定义 const 全局变量应注意的问题

  1. 头文件重复包含和变量重复定义

  1. C++ 初始化列表

  1. C++的一大误区——深入解释直接初始化与复制初始化的区别

  1. C++构造函数初始化列表与赋值