《C/C++高质量程序设计》笔记之常量
有时我们希望某些只在类中有效。由于 #define 定义的宏常量是全局的,不能达到目的,于是想当然地觉得应该用 const 修饰成员来实现。 const 数据成员的确是存在的,但其含义却不是我们所期望的。非静态 const 数据成员是属于每一个对象的成员,只在某个对象的生存期限内是常量,而对于整个类来说它是可变的,除非是 static const 。因为类可以创建多个对象,不同的对象其 const 数据成员的值可以不同。
不能在类声明中初始化非静态 const 数据成员。因为在类的对象被创建之前,编译器无法知道该常量的值。
class A { ... const int SIZE = 100; // 错误 int array[SIZE]; // 错误,未知的 SIZE };
|
非静态 const 数据成员的初始化只能在类的构造函数的初始化列表中进行。
那么,怎样才能建立在整个类中都恒定的常量呢?应该用类中的枚举常量来实现,不过只能用于整数。
class A { ... enum { SIZE1 = 100, SIZE2 = 200 }; int array1[SIZE1]; int array2[SIZE2]; };
|
枚举常量不会占用对象的存储,它们在编译时被全部求值。
还可以使用 static const 来定义类的所有对象共享的常量。在定义时初始化。
static const int SIZE1 = 100;
|
在 C 语言中,用 const 定义的常量其实是值不能修改的变量,因此会给它分配空间。但是在 C++ 中,要看具体情况,对于基本数据类型的常量,编译器会把它放到符号表而不分配存储空间,而 ADT/UDT 的 const 对象则需要分配存储空间。还有一些情况也需要分配存储空间,例如强制声明为 extern 的符合常量或取符号常量的等操作,都将强迫编译器为这些常量分配存储空间,编译器会重新在内存中创建一个它的拷贝,通过地址访问到的就是这个拷贝而非原始的符号常量。对于构造类型的 const 常量,实际上它是编译时不允许修改的变量,如果能绕过编译器的静态类型安全检查,就可以在运行时修改其内存单元。
const long lng = 10; long *pl = (long *)(&lng); *pl = 1000; cout << *pl << endl; // 1000, 修改的是拷贝 cout << lng << endl; // 10,原始常量没变,(注:本人认为是编译器的实现是直接用10替换了 lng)
class Integer { public: Integer() : m_lng(100) {} long m_lng; }; const Integer int_l; Integer *pInt = (Integer *) (&int_l); pInt->m_lng = 1000; cout << pInt->m_lng << endl; // 1000 cout << int_l.m_lng << endl; // 1000
|
const 符号只是编译时强类型安全检查机制的一种手段,以帮助程序员发现无意中修改它们的代码并进行纠正,而在运行时无法阻止恶意的修改。
阅读(885) | 评论(0) | 转发(0) |