类中定义常量

时间:2022-10-29 13:29:13

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

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

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

//   ...
};
一眼望去,c1的定义似乎更加直截了当,但别忘了只有static的整型或枚举型量才能如此初始化。这就很有局限性,例如:
class   Y   {
const   int   c3   =   7;//   error:   not   static
static   int   c4   =   7;//   error:   not   const
static   const   float   c5   =   7;//   error   not   integral
};
我还是更喜欢玩“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
//   ...
}

 

const   int   和const   浮点型可以在类中定义,既然已经定义过了,编译器就会为它分配内存。那么类外的const   int   A::i;就不会被视为定义而被编译器认为是一个重复申明,所以就不必要了。
而普通类型,如static   char*   p在类中的只是申明,编译器不会为它分配内存,所以要在类外执行一个定义,为p分配内存。
如:
class   A{
    static   char   *p;     //申明
}

char*   A::p;     //定义,为p分配内存,否则后面程序有调用p则显示unresolved   symbol   p

c++标准中仍然是只有integer类型的数据可以在类内初始化(注意是初始化,不是定义),并且还是必须在类外定义。
而上面几位说的都是对的,那些只是编译的扩展,而不是标准了。

在类中定义常量的几个做法

方法一:(错误)

class Test

{

  const int size = 100;

  int array[size];

//……

};

 

错误原因:

1:因为在一个类中,const恢复了它在c中的一部分意思,在每个类对象里分配存储并代表一个值,这个值一旦被初始化以后就不能被改变。所以在类中使用了const的意思是:在这个对象的生命周期内,它是一个常量。

然而,每个对象可能包含不同的值。

2:对const常量进行了初始化,C++中这个初始化必须由构造函数完成,如const常量在初始化列表中进行初始化。


方法二:(正确,有缺陷)

使用enum;

class Test

{

  enum { size = 100};

  int array[size];

//……

};

 

使用enum不会占用对象中的存储空间的,枚举常量在编译的时候被全部求值。

缺点:

假如定义一个非整型的常量该如何?enum无法完成此项操作,同时丧失了枚举本来的作用。

 

方法三:(正确,最好)

使用静态常量;

class Test

{

  static const int size;

  int array[size];

//……

};

const int Test::size = 100;

 

它既是常量,不能改变,又是静态,在类中只有一个定义点。所以能够完成任务。

同时,它可以定义任何与定义类型的常量。