enum枚举类型用法



在实际的编程应用中,有的变量只有几种可能的取值,譬如说一个家族的几个成员,性别的两种可能等等。C++为这种类型的变量的定义提供了enum关键字

要使用枚举类型的变量,首先需要先定义一个枚举类型名,再声明变量是该枚举类型的。



1. 枚举类型和枚举变量

1.1 枚举类型的定义和声明

之所以被称为枚举类型,就是因为命名常量是作为数据类型定义的一部分而枚举或列出的,以下是枚举类型声明的示例:

enum Roster { 	//该语句定义了Roster这一枚举类型 
	Tom,
	Sharon, 
	Bill, 
	Teresa, 
	John
}; 

// 定义匿名的枚举变量,只能使用a这一个枚举类型的变量,不能再定义其他该类型的枚举变量
enum  {Jan=1,Feb,Mar,Apr,May,Jun,Jul,Aug,Sep,Oct,Nov,dec} a;

// typedef  enum则是用来定义一个数据类型,那么该类型的变量值只能在enum定义的范围内取
typedef enum  {Jan=1,Feb,Mar,Apr,May,Jun,Jul,Aug,Sep,Oct,Nov,dec} Day;

// 定义enum/枚举类型的同时,声明变量
enum Month {Jan=1,Feb,Mar,Apr,May,Jun,Jul,Aug,Sep,Oct,Nov,dec} a,b;

上述例子中的Tom、Sharon等称为 枚举元素枚举常量(本人更倾向于称其为枚举常量,因为这样可以反映其性质),它们是用户自定义的标识符而已。

默认/不显示说明情况下,编译器设置第一个枚举量为 0,下一个为 1,以此类推(没有显示说明下步长为1)。在上述示例中,Tom 的值将是 0,Sharon 的值为 1,等等。最后一个枚举量 John 的值为 4。


1.2 枚举变量的定义和声明

enum 语句实际上并没有创建任何变量,只是定义了一个枚举类型。当以后创建这个数据类型的变量时,它们看起来就是整数,并且这些整数的值被限制在与枚举集合中的符号名称相关联的整数上。以下语句定义了两个 Roster 数据类型的变量:

enum Roster grandfather; //该语句声明了一个枚举类型的变量
enum Roster student;

此语句的形式与其他任何变量定义一样,首先是数据类型名称,然后是变量名称。数据类型名称是 Roster,而不是 enum Roster。

注意:

  • 不同枚举类型中的枚举常量的名字必须互不相同;
  • 同一枚举类型中的不同的枚举常量可以具有相同的值。

前述语句已经创建 student 这一枚举变量,也可直接定义并赋值,操作如下:

student = Sharon;
enum Roster stu1 = John;


2. 枚举变量和枚举常量的关联对应

如前所述,默认情况/不显示说明的情况下,枚举列表中的符号将被赋给整数值 0、1、2 等等

枚举列表中的符号如果不合适,则可以指定要赋给的值,如以下示例所示:

enum Department { factory = 1, sales = 2, warehouse = 4 };

如果为枚举符号赋值,则它们必须是整数。以下赋值语句将产生错误:

enum Department { factory = 1.1, sales = 2.2, warehouse = 4.4 }; //错误

虽然没有要求按升序排列赋给的整数值,但一般默认是这样。

如果在赋值时省略了一个或多个符号,则它们将被赋给一个默认值,以下两个示例:

//示例1
enum Colors { red, orange, yellow = 9, green, blue };

在该示例中,命名常量 red 将被赋值为 0,orange 将为 1,yellow 将为 9,green 将为 10,blue 将为 11。

//示例2
enum Rooms { livingroom = 1, den, bedroom, kitchen };

在该示例中,livingroom 被赋值为 1,den 将为 2,bedroom 将为 3,kitchen 将为 4。



3. 枚举类型和变量的应用

3.1 作为判断语句中的逻辑

if (student == Sharon)
  • 枚举常量和枚举变量可以用于判断语句,实际用于判断的是其中实际包含的值
    以上 if 条件语句中Sharon没有引号包围。因为它是一个枚举/命名常量,而不是字符串常量。也即是枚举数据类型的目的之一是符号名称有助于使程序自我解释。但是,由于这些名称不是字符串,它们仅在程序中使用。在使用 Roster 数据类型的示例中,以下两个语句将输出一个2,而不是名称 Sharon:
//使用常规的手段输出无法输出枚举常量所对应的字符串,因为枚举常量为整型值
Roster student1 = Sharon;
cout << student1;
//语句输出:
//>2
  • 即使枚举数据类型中的值实际存储为整数,也不能总是将整数值替换为符号名称。例如,不能使用下面语句将 Sharon 赋值给 student:
student = 1; //错误
  • 但是,可使用整数值或枚举常量名称来测试枚举变量。例如,以下两个 if 语句是等效的:
if (student == Bill) 
if (student == 2)
  • 还可以使用关系运算符来比较两个枚举变量,实际比较的是枚举变量实际包含的值的大小。例如,以下 if 语句确定存储在 student1 中的值是否小于存储在 student2 中的值。如果 student1 等于 Bill,student2 等于 John,则该语句为 true。但是,如果 student1 等于 Bill,而 student2 等于 Sharon,则该语句将为 false。
if (student1 < student2)
  • 因为枚举数据类型的符号名称与整数值相关联,所以它们可以在 switch 语句中使用,如下面的程序所示,该程序还演示了可以只使用枚举类型,而不实际创建该枚举类型的任何枚举变量。
#include <iostream>
using namespace std;
	
// Declare the enumerated type
enum Roster { Tom = 1, Sharon, Bill, Teresa, John };
// Sharon - John will be assigned default values 2-5.
int main() {
	int who;
	cin >> who;
	switch (who) {
		case Tom :
	    	cout << "Tom's birthday is January 3.\n";
	        break;
	    case Sharon :
	        cout << "Sharon's birthday is April 22.\n";
	        break;
	    case Bill :
	        cout << "Bill's birthday is December 19.\n";
	        break;
	    case Teresa :
	        cout << "Teresa's birthday is February 2.\n";
	        break;
	    case John :
	        cout << "John's birthday is June 17.\n";
	        break;
	    default :
	        cout << "Invalid selection\n";
	}
	return 0;
}
	
//程序运行结果:
//>2
//Sharon's birthday is April 22.

3.2 一次定义多个常量

比如程序中处理的问题与星期几有关,可能要将星期一转换为数字1,星期二转换为数字2,一直到数字7,在不用enum关键字的情况下,可以使用define来定义,但是会觉得很麻烦,因为因为要一个个的定义,星期的就只有7天,如果是月份,一年有12个月份,那就要写12个define,非常不方便,相反,如果使用enum的话就会非常的方便。

#include<stdio.h>
 
enum week {Mon=1,Tue,Wed,Thu,Fri,Sat,Sun};
 
int main()
{
    printf("%d",Tue);
    return 0;
}

这样定义后,Mon的值为1,Tue的值为2,Wed的值为3,依次类推。 然后就可以像使用define之后的常量一样的使用定义的7个值了。

当然也可以为每个枚举的变量都赋值,这样就和全都用define定义是一样的了。


3.3 限定变量的范围

比如我们的应用程序中要处理有关月份的东西,显然月份只能取1-12中的某个数字,为了保证程序的正确性和健壮性,我们应该使用enum。

#include<stdio.h>
 
enum Month {Jan=1,Feb,Mar,Apr,May,Jun,Jul,Aug,Sep,Oct,Nov,dec};
 
int main()
{
    enum Month a =  Feb;
    printf("%d",a);
    return 0;
}

比如像这样,定义的枚举类型 a 的取值只能是那12个变量中的一个,如果赋予了其他的变量,编译器就会报错。


3.4 enum hack:用于初始化类内数组

摘自《Effective C++》条款02

有时候编译器(错误地)不允许“static 整数型 class常量”完成“in class初值设定”,这时可改用所谓的“the enum hack"补偿做法。
其理论基础为:一个属于枚举类型(enumerated type的数值可充当ints来使用。示例如下:

class GamePlayer {
private:
	enum { NumTurns = 5 }; //"the enum hack"——令NumTurns
						   //成为5的一个记号名称
	int scores[NumTurns];  //这就没问题了
	...
};

int main() {
	//非类内的静态整形常量是可以对数组进行初始化的,以下代码不会报错
	const static int arraySize = 5;
	int array[arraySize];
}
  • enum hack行为某方面来说比较像#define而不像const,例如取const常量是合法的,但是#define和enum取地址就是不合法的;
  • 如果不想让使用者获得一个pointer或reference来指向你定义的某整数常量,则以enum可代替const int实现该约束;
  • 有些编译器会为const int类型常量另开空间存储,而enum变量却不会,有时会更省空间。


4. 总结

  • 枚举常量之间用逗号隔开,最后一个枚举常量之后不需要逗号;
  • 整个枚举类型定义语句的最后需要一个分号;
  • Roster是该枚举类型的名字,这是一个可选项;
  • 不能对枚举常量进行赋值操作(定义枚举类型时除外);
  • 枚举常量和枚举变量可以用于判断语句,实际用于判断的是其中实际包含的值;
  • 一个整数不能直接赋值给一个枚举变量,必须用该枚举变量所属的枚举类型进行类型强制转换才行;
  • 使用常规的手段输出无法输出枚举常量所对应的字符串,因为枚举常量为整型值;
  • 在使用枚举变量的时候,我们不关心其值的大小,而是其表示的状态;
  • enum用来定义一系列宏定义常量,相当于一系列的#define xx xx,当然它后面的标识符也可当作一个类型标识符;
  • typedef enum则是用来定义一个数据类型,那么该类型的变量值只能在enum定义的范围内取。两者在这点上是没有差别的。
  • 对enum变量取地址是不合法的,类似于#define的行为,对#define取地址也不合法(见Effective C++条款02)


5. 参考资料

  1. C语言——enum枚举类型用法解析
  2. C++ enum枚举用法攻略(超详细)
  3. C++ Primer(第5版)
  4. C语言之enum的用法和注意事项(枚举类型)
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值