关键字enum的用法



1、为什么要用enum

写程序时,我们常常需要为某个对象关联一组可选alternative属性.例如,学生的成绩分A,B,C,D等,天气分sunny, cloudy, rainy等等。

更常见的,打开一个文件可能有三种状态:input, output和append. 典型做法是,对应定义3个常数,即:

const int input = 1;

const int output = 2;

const int append = 3;

然后,调用以下函数:

bool open_file(string file_name, int open_mode);

比如,

open_file("Phenix_and_the_Crane", append);

这种做法比较简单,但存在许多缺点,主要的一点就是无法限制传递给open_file函数的第2个参数的取值范围,只要传递int类型的值都是合法的。(当然,这样的情况下的应对措施就是在open_file函数内部判断第二个参数的取值,只有在1,2,3范围内才处理。)

使用枚举能在一定程度上减轻这种尴尬(注1),它不但能实现类似于之前定义三个常量的功能,还能够将这三个值组合起来成为独一无二的组。例如:

enum open_modes {input = 1, output, append};

以上定义了open_modes为枚举类型enumeration type。每一个命名了的枚举都是唯一的类型,是一个类型标示器type specifier。例如,我们可以重新写一个open_file函数:

bool open_file(string file_name, open_modes om);

在open_modes枚举中,input, output, append称为枚举子enumerator, 它们限定了open_modes定义的对象的取值范围。这个时候,调用open_file函数和之前的方法还是一模一样:

open_file("Phenix_and_the_Crane", append);

但是,如果传递给open_file的第二个参数不是open_modes枚举类型值的话(注1),那么编译器就会识别出错误;就算该参数取值等价于input, output, append中的某个,

也一样会出错哦!例如:

open_file("Phenix_and_the_Crane", 1);

2、枚举的定义

      一个枚举是一个类型,可以保存一组由用户刻画的值。定义之类,枚举的使用很像一个整数类型。

枚举的定义具有以下形式,即以关键词enum开头,接着一个可选的枚举名,下来是由大括号{}包含着一个由逗号分隔的枚举子列表enumerators list:

enum [enumeration name] {enumerator1[=value1], enumerator2[=value2], ...};

3、枚举子的类型和取值

      枚举子的类型就是它所在的那个枚举,例如前面说到的open_modes枚举中,input,output和append等枚举子的类型都是open_modes。这种做法,其实是为了赋予用户和编译器一些有关该变量拟议中的用途的提示。

默认下,第一个枚举子被赋值0,接下来的枚举子取值是前面一个枚举子的取值+1,例如:

enum weather {sunny, cloudy, rainy, windy};

其中

sunny == 0,

cloudy == 1,

rainy == 2,

windy == 3;

以上是默认情况,有时候我们希望显式地指定某个枚举子的值,那么会出现什么情况呢?看看:

enum some_fruit {apple = 3, orange, banana = 4, bear};

好了,apple == 3, banana == 4; 那么orange和bear呢?记得前面说过一句,默认下”接下来的枚举子取值是前面一个枚举子的取值+1“。既然这两个枚举子没有显式赋值,那么就按照默认规则办事,所以 orange == 4, bear == 5.

从这个例子也可以看出,同一枚举中枚举子的取值不需要唯一。这样有什么用处呢?下面是个简单的例子:

enum some_big_cities {

Guangzhou = 4,

Shenzhen    = 4,

Hongkong   = 4,

Shanghai    = 2,

Beijing         = 3,

Chongqi      = 3

};

以上简单地按区域,将五个城市按照华南(4),华东(2), 华北(3)的几个城市分类了。

4、枚举变量的定义、初始化和赋值

既然每个枚举都是一个类型,那么由这个类型自然可以声明变量,例如,由前面定义的some_big_cities:

some_big_cities where_I_am;

需要注意的是,在声明where_I_am时没有初始化,如果这时打印where_I_am的值:

enum some_big_cities {

Guangzhou = 4,

Shenzhen = 4,

Hongkong = 4,

Shanghai = 2,

Beijing = 3,

Chongqi = 5};

int main(void)

{

some_big_cities wh;

cout<<"the value is: "<<wh<<endl;

return 0;

}

输出将是the value is: 1. 然而,如果声明wh为全局变量,则另一种情况:

enum some_big_cities {Guangzhou = 1 Shenzhen = 1, Hongkong = 1,

Shanghai = 2, Beijing = 3, Chongqi = 5};

some_big_cities wh;

int main(void)

{

cout<<"the value is: "<<wh<<endl;

return 0;

}

输出将是the value is: 0;

以上结果是在Visual C++ 2005 Express中得到,不知道其它编译器情况如何,也不知为什么得到这样的结果。下来再找找资料。

定义一个枚举变量时,可以给它初始化,例如:

some_big_cities wh = Guangzhou;

注意等号右边只能取枚举子中的某一个;特别地,以Guangzhou为例,虽然Guangzhou==4, 但以下初始化是出错的:

some_big_cities wh = 4;

Visual C++ 2005编译器提示:

error C2440: ‘initializing‘ : cannot convert from ‘int‘ to ‘some_big_cities‘

      可见,不能直接地把一个整型赋值给一个枚举变量,因为枚举和整型是不同类型的,除非显式转换。关于枚举与整型的关系,后面再讲。

除了初始化,枚举变量也有赋值运算:

some_big_cities wh;

wh = Guangzhou;

wh = Shanghai;

或者

some_big_cities wh1 = Guangzhou;

some_big_cities wh2 = Shanghai;

wh2 = wh1;

5、枚举的取值范围

   如果某个枚举中所有枚举子的值均非负,该枚举的表示范围就是[0:2^k-1],其中2^k是能使所有枚举子都位于此范围内的最小的2的幂;如果存在负的枚举值,该枚举的取值范围就是[-2^k,2^k-1].例如:

enum e1 {dark, light}; //范围0:1

enum e3 {min = -10, max = 1000}; //范围-1024:1023

6、枚举与整型的关系

    整型值只能显式地转换成一个枚举值,但是,如果转换的结果位于该枚举取值范围之外,则结果是无定义的。

enum e1 {dark = 1, light = 10};

e1 VAR1 = e1(50); //无定义

e1 VAR2 = e1(3); //编译通过

在这里也说明了不允许隐式地从整型转换到枚举的原因,因为大部分整型值在特定的枚举里没有对应的表示。

至于枚举可以当作特定的整型数来用的例子,从open_modes可以体会。

7、自定义运算符

      枚举是用户自定义类型,所以在用户可以为它定义自身的操作,例如++或者<<等。但是,在没有定义之前,不能因为枚举像整型就可以默认使用,例如:

enum SomeCities

{

zhanjiang,

Maoming,

Yangjiang,

Jiangmen,

Zhongshan

};

SomeCities oneCity=  Yangjiang;

for (oneCity = zhanjiang; oneCity != Zhongshan; ++oneCity)

{

cout<<oneCity<<endl;

cout<<oneCity+  Yangjiang<<endl;//正确

cout<<oneCity+oneCity<<endl;//正确

}

以上的++OneCity是没有定义的,在Visual C++ 6 编译下得到如下错误:

error C2675: unary ‘++‘ : ‘enum main::SomeCities‘ does not define this operator or a conversion to a type acceptable to the predefined operator

8、Sizeof

一个枚举类型的sizeof就是某个能够容纳其范围的整型的sizeof, 而且不会大于sizeof(int), 除非某个枚举子的值不能用int或者unsigned int来表示。

在32位机器中,sizeof(int)一般等于4。前面介绍的所有枚举,例如,

enum SomeCities

{

zhanjiang,

Maoming,

Yangjiang,

Jiangmen,

Zhongshan

};

计算其sizeof, 可能是1,也可能是是4。在我的intel E2160双核、32位机器中,得到4。

-----------------------------------------------------------------------------------

[注1, Begin]

由于通过将整型数显式转换就可能得到对应枚举类型的值,所以声明一个枚举来达到限制传递给函数的参数取值范围还是力不从心的,以下是一个例子:

enum SomeCities

{

zhanjiang=1, //1

Maoming,     //2

Yangjiang,   //3

Jiangmen,   //4

Zhongshan = 1000 //1000

};

void printEnum(SomeCities sc)

{

cout<<sc<<endl;

}

int main(void)

{

SomeCities oneCity = SomeCities(50); //将50通过显式转换,为oneCity赋值

printEnum(oneCity); //在VC++ 6 编译器下得到50输出

return 0;

}

以上例子说明,虽然SomeCities的定义里没有赋值为50的枚举值,但是,由于50在该枚举的取值范围内,所以通过显式声明得到一个有定义的枚举值,从而成功传递给printEnum函数。

[注1, End]

关键字enum的用法

时间: 2024-10-21 21:10:35

关键字enum的用法的相关文章

李洪强iOS开发之 - enum与typedef enum的用法

李洪强iOS开发之 - enum与typedef enum的用法 01 - 定义枚举类型 上面我们就在ViewController.h定义了一个枚举类型,枚举类型的值默认是连续的自然数,例如例子中的TO_BE_PAID=0,//开始   那么其后的就依次为1,2,3....所以一般只需要设置枚举中第一个的值就可以. 注意: 在定义枚举类型的时候一定要定义在.h中的#imort 和€interface之间定义,位置不能错了 02 - 定义操作类型 enum和enum typedef 在IOS中的使

iOS开发之 typedef enum 和enum的用法

一,两者的用法 枚举类型定义用关键字enum标识,形式为: enum 标识符 { 枚举数据表 }: 枚举数据(枚举常量)是一些特定的标识符,标识符代表什么含义,完全由程序员决定.数据枚举的顺序规定了枚举数据的序号,从0开始,依次递增. enum status { copy, delete }: 枚举类型status仅有两个数据,一个是copy,一个是delete,序号为0.1,代表复制与删除. enum status { copy=6, delete }: 则copy的序号为6,delete的序

C++ new的nothrow关键字和new_handler用法

C++ new的nothrow关键字和new_handler用法 new && new(std::nothrow) new(std::nothrow) 顾名思义,即不抛出异常,当new一个对象失败时,默认设置该对象为NULL,这样可以方便的通过if(p == NULL) 来判断new操作是否成功 普通的new操作,如果分配内存失败则会抛出异常,虽然后面一般也会写上if(p == NULL) 但是实际上是自欺欺人,因为如果分配成功,p肯定不为NULL:而如果分配失败,则程序会抛出异常,if语

c#Enum的用法

public enum ResType { Role = 0, Dept = 1, Group = 2, Site = 3, Org = 4, Sub=8 } 这里定义了一个enum    ResType 用ResType type=ResType.Sub 可以定义一个枚举,(int)type得到的结果是8,type.ToString() ,结果是"Sub" c#Enum的用法

C# defualt关键字默认值用法

原文:C# defualt关键字默认值用法 默认值表达式生成类型的默认值. 默认值表达式在泛型类和泛型方法中非常有用. 使用泛型类和泛型方法时出现的一个问题是,如何在无法提前知道以下内容的情况下将默认值赋值给参数化类型 T: T 是引用类型还是值类型. 如果 T 是值类型,它是数值还是用户定义的结构. 已知参数化类型 T 的变量 t,仅当 T 为引用类型时,语句 t = null 才有效. 赋值 t = 0 仅对数值类型有效,对结构无效. 解决方案是使用默认值表达式,该表达式对引用类型(类类型和

深入Java关键字this的用法的总结

在Java程序设计中经常会见到this的使用,this使得程序设计变得规范.简单.灵活.但是在使用过程中,在不同场 合它的含义并不完全相同,使用不当还会出现错误, 本文对this的几种用法和出现的问题进行了分析详解. 关键词:类:对象:this:成员变量:方法:构造方法 中,Java语言提供了丰富的类(Class).接口(Interface)以及相应的方法(Method). 使用这些类或接口,用户可以定义 自己的类或子类,并以这些类为模板创建对象(Object). 在Java语言中,当创建一个对

Java enum的用法详解

在JDK1.5 之前,我们定义常量都是: public static fianl.... .现在好了,有了枚举,可以把相关的常量分组到一个枚举类型里,而且枚举提供了比常量更多的方法. public enum Color { RED, GREEN, BLANK, YELLOW } 用法二:switch JDK1.6之前的switch语句只支持int,char,enum类型,使用枚举,能让我们的代码可读性更强. enum Signal { GREEN, YELLOW, RED } public cl

extern关键字的一般用法

extern关键字会提升变量或者函数的逼格,使得它们可以跨文件被访问.话虽然是这么说,使用这个关键字必须要注意一些东西. 首先,你得在cpp文件里面实现这些全局变量和全局函数,这是最基本的,然后只需要在需要用到这些变量和函数的文件里声明一下,用extern修饰声明,这样弄完之后就可以随意使用这些全局变量和全局函数了.请不要为编译器担心,担心它们找不到这些东西,只要你实现了,不怕编译器找不到. 在别的文件里写一堆的extern声明显得特别不专业,也显得代码十分臃肿,有没有好的做法呢?有的. 我们一

【转】Java enum的用法详解

用法一:常量 在JDK1.5 之前,我们定义常量都是: public static fianl.... .现在好了,有了枚举,可以把相关的常量分组到一个枚举类型里,而且枚举提供了比常量更多的方法. public enum Color { RED, GREEN, BLANK, YELLOW } 用法二:switch JDK1.6之前的switch语句只支持int,char,enum类型,使用枚举,能让我们的代码可读性更强. enum Signal { GREEN, YELLOW, RED } pu