您的位置:首页 > 编程语言 > C语言/C++

C++中常量的定义与使用

2012-02-02 01:00 281 查看
在C中,我们定义一个常量,通常会使用宏来定义:

#define int CONST_VALUE 100

由于C++是兼容C的,所以,在C++中,这种定义常量的方式同样允许,而且,在C++中又增加了两种定义常量的方式:

(1)在常量定义的时候使用关键字const

(2)定义一个enum类型,使用其成员表示一个常量

所以,在C++中有三种方式可以定义一个常量,但是,三种定义常量的方式背后的原理是不同的。

当我们使用#define定义一个常量的时候,其表示的方式是由预处理器处理的。预处理器是在编译器被调用之前调用的一个独立的程序,预处理器的作用主要是删除注释,包含相关文件、以及相关的宏代替等。在宏代替中,又包含了两种代替,一种是函数的代替,另一个则是我们上面所说的常量的代替。也就是说,在C++编译器开始编译程序的时候,我们使用宏定义的常量已经被预处理器给处理了一次。这里的处理方式很简单,只是单纯的将代码中的宏名替换为我们所定义的常量值,对于我们的例子来说,就是将代码中的CONST_VALUE替换成100,当编译器开始编译程序的时候,我们的代码中已经看不到我们使用的CONST_VALUE这个常量名,取而代之的是它的值100。或许有人会说,这很正常啊,本来我们就是用的100这个常量值。但是有一点必须注意,当我们的编译器开始编译程序的时候,他可能不知道CONST_VALUE这个变量,因为在编译器开始处理代码的时候,CONST_VALUE这个变量名已经被预处理器给替换成它的值100,所以,CONST_VALUE这个值压根就没有进入到记号表(symbol
table)。如果我们使用这个常量的代码段出现了一个错误,错误信息会提到100,而不是变量名CONST_VALUE,而恰恰此时,如果我们使用的这个常量是其他人所写的,我们仅仅是使用这个常量名的话,则会产生疑惑:这个值代表什么?从哪里来的呢?从而在调试程序的时候带来不必要的麻烦。归根到底,则是,使用宏定义的常量没有进入到记号表中。

注:一直没有找到测试提示编译错误使用值而不是宏名的方法,如果有朋友有测试代码,望不吝指教。

然而,当我们使用cosnt或者enum定义一个常量的时候:

const int Const_Value = 100;



enum

{

CONST_VALUE = 100,

};

则在预处理阶段不会将我们的变量名给替换成相应的常量值,所以,在编译器处理代码的时候,会将相应的常量名放入到记号表中,如果在编译期出现错误,则会指出其常量名而不是用100这个值。这样就避免了上面出现的困惑。

因为C++是一门面向对象编程语言,不可避免的我们会使用类来进行相关功能的实现。此时,如果我们定义一个类如下:

class CTest

{

public:

CTest() {}

~CTest() {}

private:

int arr_test[100];

};

我们定义的类中,有一个数据成员,它是一个由100个元素组成的整型数组。如果我们想在代码中对数组大小进行控制,可以使用一个常量代替数组大小。则修改如下:

class CTest

{

public:

CTest() {}

~CTest() {}

private:

int arr_test[COSNT_VALUE];

};

其实这样,我们的目的已经达到了,我们使用常量值CONST_VALUE代替了显示的数组大小100。但是,这样做是不是有些不妥呢?

我们知道,C++是一门面向对象编程语言,其私有数据成员仅在这个类内部的成员函数被访问(这里只考虑不存在继承体系的类以及没有友元的情况)。然后我们回到上面的例子,数组arr_test是一个私有成员,如果我们使用一个宏定义一个常量,然后用这个常量表示数组的大小,那么我们就可以在类的外部去操纵这个数组大小。这种情况下,
使类不再具有严格意义上的封装性,这是因为#define并不重视封装性。此时,我们需要用一个仅可以在类内部定义的常量来表示数组的大小。所以我们需要一个这样的常量,他可以在类的内部定义,用来表示数组的大小,而且它应该不占用内存空间,因为这个常量仅仅是用来表示类的大小,没有其他的用处,于是便有了”类专属常量“这个概念:

类专属常量的定义方法是在常量的定义前面加static关键字。这时,我们的类已经成了这个样子:

class CTest

{

public:

CTest() {}

~CTest() {}

private:

static const int CONST_VALUE = 100;

int arr_test[CONST_VALUE];

};

我们知道,static类型的变量是存储在静态存储区的,它在类中不占用内存空间,如果我们sizeof(CTest)得到的值是400,仅仅是数组arr_test的大小。这正符合我们当初的意图。至于为什么不直接用const类定义数组的大小,那是因为,cosnt与引用类型的变量必须在成员初始化列表中进行初始化,也就是说,我们编译时是不会知道我们定义的常量的值的,只有我们真正生成这个类一个对象的时候,我们所定义的常量值才知道大小。但是,作为一个数组的大小,必须是在编译器可知的一个值。如果我们直接用const去定义一个常量,则会报错。

由此我们可以,使用#define不仅不能够定义一个类的专属常量,也不具有良好的封装性。当我们需要一个这样的常量的时候,应该避免使用宏定义,取而代之的是用类的专属常量。

同样使用enum也能达到同样的效果,我们将在另外的文章中讨论这一个问题。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: