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]

c++ enum用法【转】的更多相关文章

  1. Java Enum用法详解

    Java Enum用法详解 用法一:常量 在JDK1.5 之前,我们定义常量都是: public static fianl.... .现在好了,有了枚举,可以把相关的常量分组到一个枚举类型里,而且枚举 ...

  2. MVC图片上传详解 IIS (安装SSL证书后) 实现 HTTP 自动跳转到 HTTPS C#中Enum用法小结 表达式目录树 “村长”教你测试用例 引用provinces.js的三级联动

    MVC图片上传详解   MVC图片上传--控制器方法 新建一个控制器命名为File,定义一个Img方法 [HttpPost]public ActionResult Img(HttpPostedFile ...

  3. iOS 开发-- enum与typeof enum用法

    一, 两者的用法 枚举类型定义用关键字enum标识,形式为: enum标识符 { 枚举数据表 }; enum用来定义一系列宏定义常量区别用,相当于一系列的#define ** **,当然它后面的标识符 ...

  4. C#中的枚举类型enum用法

    定义一个简单的枚举类型:   enum Days {Sat, Sun, Mon, Tue, Wed, Thu, Fri};        //这时候         Days.Sat = 0 ,后面依 ...

  5. c enum用法

    c语言中enum的用法,先用关键字enum声明一个类型如enum HUMAN {MAN ,WOMAN};这里就声明了一个HUMAN这个枚举类型.其中MAN的值为0,后面依次递增.后面要用的时候,先声明 ...

  6. 关于C与C++的struct,union,enum用法差异

    对着代码说话: #include <stdio.h> #include <stdlib.h> struct test { int abc; }; enum _enum {A,B ...

  7. List GroupBy真实用法,Reflection(反射)用法,Enum用法,正则,搜索下拉布局

    1.List  GroupBy 用法 var _roomProducts = homesingProducts.GroupBy(t => t.RoomName); RoomedProducts ...

  8. java enum用法

    基本用法 enum Day { SUNDAY, MONDAY, TUESDAY, WENDSDAY, THURSDAY, FRIDAY, SATURDAY; } 枚举是常量,所以应该用大写. 枚举是对 ...

  9. (转C#中Enum用法小结)

    enums枚举是值类型,数据直接存储在栈中,而不是使用引用和真实数据的隔离方式来存储. (1)默认情况下,枚举中的第一个变量被赋值为0,其他的变量的值按定义的顺序来递增(0,12,3...),因此以下 ...

  10. C#中Enum用法小结

      enums枚举是值类型,数据直接存储在栈中,而不是使用引用和真实数据的隔离方式来存储. (1)默认情况下,枚举中的第一个变量被赋值为0,其他的变量的值按定义的顺序来递增(0,12,3...),因此 ...

随机推荐

  1. 创建oracle数据库的表空间、用户、目录、导入\导出文件等信息

    1.创建表空间 create tablespace ts_aw logging datafile 'd:\app\Administrator\product\tablespace\ts_aw.dbf' ...

  2. HBase API详解

    一.Java API和HBase数据模型的关系 在Java中,与HBase数据库存储管理相关的类包括HBaseAdmin.HBaseConfiguration.HTable.HTableDescrip ...

  3. 拔一拔 ExtJS 3.4 里你遇到的没遇到的 BUG(1)

    本文从今天开始,我要做的就是不断的更新,不断的披露ExtJS 3.4的BUG并修复它.需要注意的是版本为3.4而不是4.0,因为4.0改动和变化比较大,所以不要对号入座. 嘿嘿,本人不怎么写东西,不过 ...

  4. html object元素

    知道object是播放音频,但是想了解具体点,百度一下,感觉模模糊糊的,感觉看不大明白,最后找到一个解释比较详细,先从应用,到解释具体属性, 具体网址是: http://www.w3school.co ...

  5. MarkDown使用 (三)表格

    MarkDown表格的用法 MarkDown表格的用法 例如: $$ \begin{array}{c|lcr} n & \text{Left} & \text{Center} & ...

  6. android小知识之意图(intent)

    android中的意图有显示意图和隐式意图两种, 显示意图要求必须知道被激活组件的包和class 隐式意图只需要知道跳转activity的动作和数据,就可以激活对应的组件 A 主activity  B ...

  7. 浅谈qt 布局器

    在一个颜值当道的今天,无论买衣服,买车还是追星,颜值的高低已经变成了大家最看重的(不管男性女性都一样,千万别和我说你不是):而对于程序猿来说,开发一款软件,不再只注重逻辑和稳定性,美观和用户友好性也是 ...

  8. JavaEE Tutorials (13) - 使用锁定控制对实体数据的并发访问

    13.1实体锁定和并发概述180 13.1.1使用乐观锁定18113.2锁模式181 13.2.1设置锁模式182 13.2.2使用悲观锁定183

  9. 类型萃取(type traits)

    1. 类型萃取的作用 类型萃取使用模板技术来萃取类型(包含自定义类型和内置类型)的某些特性,用以判断该类型是否含有某些特性,从而在泛型算法中来对该类型进行特殊的处理用来提高效率或者其他.例如:在STL ...

  10. java面向对象编程(类、对象)

    一.面向对象编程概述面向对象编程(Object  Oriented  Programming,缩写为OOP)是当今最流行的程序设计技术,它具有代码易于维护.可扩展性好和代码可常用等优点.面向对象的设计 ...