幻数——上下文里出现的字面常量。
幻数带来的主要问题是它们没有(抽象)语义。当我们阅读和维护带有幻数的代码时,不得不去一个个地搞清楚每个光秃秃的量到底代表的是什么意思。没错,这样也能勉强度日,但带来的是不必要的精力浪费以及准确性的丧失。
1 //这里的一些10分别代表什么意思??
2 class Portfolio
3 {
4 //...
5 Contact *contracts_[10];
6 char id_[10];
7 };
8
9 ......
10
11 for (int i = 0; i < 10; ++i)
12 ...
幻数的另一个不那么显而易见的坏处就是它会以意想不到的方式降低它所代表的类型的精度。
例如:4000, 它实际类型是平台相关的。
另一个字面常量带来的潜在威胁来源于它们没有地址。
给幻数起一个名字。作为一个指导原则,除了0和1之外,程序里出现的任何数大概都可以算作幻数,它们应该有自己的名字。
1 class Portfolio
2 {
3 //...
4 enum {maxContracts = 10, idLen = 10};
5 Contact *contracts_[maxContracts ];
6 char id_[idLen ];
7 };
在其所在作用域有着明确含义的枚举常量,有着不占空间,也没有任何运行期成本的巨大优点。
把数定义为常数,不要定义为宏。C语言的传统方式是使用#define行来对付幻数。C语言预处理程序是一个强有力的工具,但是它又有些鲁莽。使用宏进行编程是一种很危险的方式,因为宏会在背地里改变程序的词法结构。我们应该让语言去做正确的工作(C预处理命令本身不是C语言的组成部分)。
在c/c++里,整数常数可以用枚举语句声明。在C++里,任何类型都可以使用const声明的常数:
1 const int MAXROW = 24, MAXCOL = 80;
在Java里,可以用final声明:
1 static final int MAXROW = 24, MAXCOL = 80;
C语言也有const值,但是他们不能用作数组的界。这样,enum就是C中唯一可用的选择了。