C++类中常量定义

有时我们希望某些常量只在类中有效。由于#define定义的宏常量是全局的,不能达到目的,于是想当然地觉得应该用const修饰数据成员来实现。const数据成员的确是存在的,但其含义却不是我们所期望的。const数据成员只在某个对象生存期内是常量,而对于整个类而言却是可变的,因为类可以创建多个对象,不同的对象其const数据成员的值可以不同。

 

    (1)不能在类声明中初始化const数据成员。

以下用法是错误的,因为类的对象未被创建时,编译器不知道SIZE的值是什么。

    class A

    {…

        const int SIZE = 100;     // 错误,企图在类声明中初始化const数据成员

        int array[SIZE];        // 错误,未知的SIZE

    };

 

 

(2)const数据成员的初始化只能在类构造函数的初始化表中进行

例如

    class A

    {…

        A(int size);     // 构造函数

        const int SIZE ;

    };

    A::A(int size) : SIZE(size)    // 构造函数的初始化表

    {

    …

    }

    A a(100); // 对象 a 的SIZE值为100

    A b(200); // 对象 b 的SIZE值为200

 

 

    (3)怎样才能建立在整个类中都恒定的常量呢?别指望const数据成员了,应该用类中的枚举常量来实现。

       例如

    class A

    {…

        enum { SIZE1 = 100, SIZE2 = 200}; // 枚举常量

        int array1[SIZE1];

        int array2[SIZE2];

    };

    枚举常量不会占用对象的存储空间,它们在编译时被全部求值。枚举常量的缺点是:它的隐含数据类型是整数,其最大值有限,且不能表示浮点数(如PI=3.14159)。

//------------------------------------------------------------------------

如果你想得到一个可用于常量表达式中的常量,例如数组大小的定义,那么你有两种选择:

 class X {
  static const int c1 = 7;
  enum { c2 = 19 };

  char v1[c1];
  char v2[c2];

  // ...
 };
一眼望去,c1的定义似乎更加直截了当,但别忘了只有static const的整型或枚举型量才能如此初始化。
这就很有局限性,例如
 class Y {
  const int c3 = 7;  // error: not static
  static int c4 = 7;  // error: not const
  static const float c5 = 7; // error not integral
 };
(在自己的VC++6.0运行static const int c1 = 7;是报错的,估计是编译器太老了)
我还是更喜欢玩“enum戏法”,因为这种定义可移植性好,而且不会引诱我去使用非标准的“类内初始化”扩展语法。

那么,为何要有这些不方便的限制?因为类通常声明在头文件中,而头文件往往被许多单元所包含。但是,为了避免链接器设计的复杂化,C++要求每个对象都只能被定义一次。如果C++允许类内定义要作为对象被存在内存中的实体,那么这项要求 就无法满足了。

关于C++设计时的一些折衷,参见《The Design and Evolution of C++》。

如果这个常量不需要被用于常量表达式,那么你的选择余地就比较大了:

 class Z {
  static char* p;  // initialize in definition
  const int i;  // initialize in constructor
 public:
  Z(int ii) :i(ii) { }
 };

 char* Z::p = "hello, there";

 
 
只有当static成员在类外被定义了,你才可以获取它的地址,例如:
 class AE {
  // ...
 public:
  static const int c6 = 7;
  static const int c7 = 31;
 };

 const int AE::c7; // definition

 int f()
 {
  const int* p1 = &AE::c6; // error: c6 not an lvalue
  const int* p2 = &AE::c7; // ok
  // ...
 }

  • 6
    点赞
  • 16
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值