1 问题引入
-
问题:类中是否可以定义
const
成员? -
示例:下面的类定义是否合法?如果合法,
ci
的值是什么,存储在哪里?-
Demo
#include <stdio.h> class Test { private: const int ci; public: int getCI() { return ci; } }; int main() { Test t; printf("t.ci = %d ", t.getCI()); return 0; }
-
编译
test.cpp: In fuction 'int main()': test.cpp:14: error: structure 't' with uninitialized const members
-
说明:类中可以定义
const
成员,但通过这个类类型定义对象时,编译器会报错:会对该const
成员进行初始化 -
修改:利用构造函数进行
const
成员的初始化#include <stdio.h> class Test { private: const int ci; public: Test() { ci = 10; } int getCI() { return ci; } }; int main() { Test t; printf("t.ci = %d ", t.getCI()); return 0; }
-
编译
test.cpp: In constructor 'Test::Test()': test.cpp:8: error: uninitialized member 'Test::ci' with 'const' type 'const int' test.cpp:10: error: assignment of read-only data-member 'Test::ci'
-
说明:类的
const
成员必须用列表初始化
-
2 类成员的列表初始化
-
C++ 中提供了初始化列表对成员变量进行初始化
-
语法规则
ClassName::ClassName(): m1(v1),m2(v1,v2),m3(v3) { //some other initialize operator }
-
注意事项
-
成员的初始化顺序与成员的声明顺序相同
-
成员的初始化顺序与初始化列表中的位置无关
- 虽然
m1
在前,但m1
的初始化不一定在m2
、m3
之前,依赖于它们的声明顺序
ClassName::ClassName(): m1(v1),m2(v1,v2),m3(v3) { //some other initialize operator }
- 虽然
-
初始化列表先于构造函数的函数体执行
- 当构造函数的函数体执行的时候,类的对象已经构建完毕,执行构造函数的函数体只是为了初始化这个对象的状态而已
- 列表初始化是为了初始化,是在类的对象创建之前执行的,这是初始化和赋值之间的差异
-
-
示例:初始化列表的使用
-
Demo
#include <stdio.h> class Value { private: int mi; public: Value(int i) { printf("i = %d ", i); mi = i; } int getI() { return mi; } }; class Test { private: Value m2; Value m3; Value m1; public: Test() : m1(1), m2(2), m3(3) //类的类类型成员必须使用列表初始化 { printf("Test::Test() "); } }; int main() { Test t; return 0; }
-
编译运行
i = 2 i = 3 i = 1 Test::Test()
-
3 类中的 const 成员
-
类的
const
成员会被分配空间 -
类的
const
成员的本质是只读变量 -
类的
const
成员只能在初始化列表中指定初始值 -
编译器无法直接得到 类的
const
成员的初始值,因此无法进入符号表成为真正意义上的常量 -
示例:只读成员变量
-
Demo
#include <stdio.h> class Value { private: int mi; public: Value(int i) { printf("i = %d ", i); mi = i; } int getI() { return mi; } }; class Test { private: const int ci; Value m2; Value m3; Value m1; public: Test() : m1(1), m2(2), m3(3), ci(100) { printf("Test::Test() "); } int getCI() { return ci; } int setCI(int v) { int* p = const_cast<int*>(&ci); *p = v; } }; int main() { Test t; printf("t.ci = %d ", t.getCI()); t.setCI(10); printf("t.ci = %d ", t.getCI()); return 0; }
-
编译运行
i = 2 i = 3 i = 1 Test::Test() t.ci = 100 t.ci = 10
-
-
初始化与赋值的不同
- 初始化:对正在创建的对象进行初值设置
- 赋值:对已经存在的对象进行值设置