13.1 枚举类型

最后更新于:2022-04-01 06:24:01

上一章我们谈到了从真实世界的值(如扑克牌中的大小和花色)到程序世界内部表示(如整数或字符串)的映射。虽然我们实现了牌面大小和整型数、花色和整型数之间的映射,但必须指出,映射本身并没有成为程序的一部分。 实际上,C++提供了一种称为“**枚举类型**”的特性使以下两点成为可能,一是将映射作为程序的一部分,一是定义了组成映射的值的集合。比如,牌的花色(Suit)和大小(Rank)可以以枚举的形式定义: ~~~ enum Suit { CLUBS, DIAMONDS, HEARTS, SPADES }; enum Rank { ACE=1, TWO, THREE, FOUR, FIVE, SIX, SEVEN, EIGHT, NINE, TEN, JACK, QUEEN, KING }; ~~~ 默认情况下,枚举类型中的第一个值映射为0,第二个映射为1,以此类推。如在Suit类型中,CLUBS(梅花)使用整型数0表示, DIAMONDS(方块)使用1表示,等等。 Rank的定义中将ACE指定为1,覆盖了默认的映射值。其他值以自然的方式递推。 定义了这些类型之后,我们就可以在任何地方使用它们。比如,实例变量rank和suit可以分别用类型Rank和Suit来声明: ~~~ struct Card { Rank rank; Suit suit; Card (Suit s, Rank r); }; ~~~ 构造函数的参数类型也相应改变了。现在,我们可以以枚举类型的值为参数创建Card对象: ~~~ Card card (DIAMONDS, JACK); ~~~ 一般约定,枚举类型中值的名字全部用大写字母表示。上面代码要比下面使用整型数的方式清晰地多: ~~~ Card card (1, 11); ~~~ 枚举类型中的值是用整型数表示的,所以可用作向量的下标。因此原来的print函数不加修改即可工作。不过buildDeck还是要做些修改,如下: ~~~ int index = 0; for (Suit suit = CLUBS; suit <= SPADES; suit = Suit(suit+1)) { for (Rank rank = ACE; rank <= KING; rank = Rank(rank+1)) { deck[index].suit = suit; deck[index].rank = rank; index++; } } ~~~ 从某种程度上说,枚举类型的使用会让代码的可读性更好,不过同时也带来了一点混乱。严格地讲,不允许在枚举类型上执行数学运算,如suit++是不合法的。 而另一方面,在表达式suit+1中,C++自动将枚举类型转换为整型数,然后我们可以将结果强制转换为枚举类型: ~~~ suit = Suit(suit+1); rank = Rank(rank+1); ~~~ 当然,还有一种更好的处理方法,那就是为枚举类型重载++操作符,但这已经超出本书的范围了。 [](http://www.ituring.com.cn/article/5353)
';