5.1 强类型枚举

类别:部分人

5.1.1 枚举:分门别类与数值的名字

枚举类型是C及C++中一个基本的内置类型,不过也是一个有点“奇怪”的类型。从枚举的本意上来讲,就是要定义一个类别,并穷举同一类别下的个体以供代码中使用。由于枚举来源于C,所以出于设计上的简单的目的,枚举值常常是对应到整型数值的一些名字。比如:


enum Gender{Male,Female};


定义了Gender(性别)枚举类型,其中包含两种枚举值Male及Famale。编译器会默认为Male赋值0,为Famale赋值1。这是C对名称的简单包装,即将名称对应到数值。

而枚举类型也可以是匿名的,匿名的枚举会有意想不到的用处。比如当程序中需要“数值的名字”的时候,我们常常可以使用以下3种方式来实现。

第一种方式是宏,比如:


define Male 0

define Female 1


宏的弱点在于其定义的只是预处理阶段的名字,如果代码中有Male或者Female的字符串,无论在什么位置一律将被替换。这在有的时候会干扰到正常的代码,因此很多时候为了避免这种情况,程序员会让宏全部以大写字母来命名,以区别于正常的代码。

而第二种方式——匿名的enum的状况会好些。


enum{Male,Female};


这里的匿名枚举中的Male和Female都是编译时期的名字,会得到编译器的检查。相比于宏的实现,匿名枚举不会有干扰正常代码的尴尬。

不过在C++中,更受推荐是第三种方式——静态常量。如:


const static int Male=0;

const static int Female=1;


Male和Female的名字同样得到编译时期检查。由于是静态常量,其名字作用域也被很好地局限于文件内。不过相比于enum,静态常量不仅仅是一个编译时期的名字,编译器还可能会为Male和Female在目标代码中产生实际的数据,这会增加一点存储空间。相比而言,匿名的枚举似乎更为好用。

不过事实上,这3种“数值的名字”的实现方式孰优孰劣,程序员们各执一词。不过枚举类型的使用的独特性则是无需质疑的。

注意 历史上,枚举还有一个被称为“enum hack”的独特应用,在上面的静态常量的例子中,如果static的Male和Female声明在class中,在一些较早的编译器上不能为其就地赋值(赋值需要在class外),因此有人也采用了enum的方式在class中来代替常量声明。这就是“enum hack”。

虽然enum确实有些“奇怪”的用途,不过作为“枚举类型”本身而言,enum并非完美,具体见下节。