枚举的用法详细总结

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;
for (oneCity = zhanjiang; oneCity != Zhongshan; ++oneCity)
{
   cout<<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函数。

(0)

相关推荐

  • FileShare枚举的使用小结(文件读写锁)

    开发过程中,我们往往需要大量与文件交互,读文件,写文件已成家常便饭,本地运行完美,但一上到投产环境,往往会出现很多令人措手不及的意外,或开发中的烦恼,因此,我对普通的C#文件操作做了一次总结,问题大部分如下: 1:写入一些内容到某个文件中,在另一个进程/线程/后续操作中要读取文件内容的时候报异常,提示 System.IO.IOException: 文件"XXX"正由另一进程使用,因此该进程无法访问此文件. 2:在对一个文件进行一些操作后(读/写),随后想追加依然报System.IO.I

  • C# 遍历枚举类型的所有元素

    比如定义了一个错误的枚举类型 复制代码 代码如下: public enum eErrorDetailCode : int         {             登陆成功 = 0,             登出 = 1,             应用错误 = 2,             成功 = 16,             失败 = 17         } 需要引用 using System; 然后在循环中,遍历枚举对象的所有元素 复制代码 代码如下: foreach (int  m

  • C#枚举数值与名称的转换实例分享

    首先建立一个枚举: 复制代码 代码如下: /// <summary>    /// 颜色    /// </summary>    public enum ColorType    {        /// <summary>        /// 红色         /// </summary>        Red, /// <summary>        /// 蓝色         /// </summary>      

  • C# 获取枚举值的简单实例

    先申明一个枚举: 复制代码 代码如下: public enum Test_Enum        {            one = 1001, two = 1002, three = 1003, four = 1004, five = 1005, six = 1006, seven = 1007, eight = 1008, nine = 1009, zero = 1000        } 获取值: 复制代码 代码如下: object ojb = Enum.GetName(typeof(T

  • 枚举类型的定义和应用总结

    定义:如果一种变量只有几种可能的值,可以定义为枚举类型.所谓"枚举类型"是将变量的值一一列举出来,变量的值只能在列举出来的值的范围内. 声明:声明枚举类型用enum开头,例如: 复制代码 代码如下: enum weekday{sun,mon,tue,wed,thu,fri,sat}; 上面声明了一个枚举类型weekday,花括号中的sun,mon,....sat等称为枚举元素或枚举常量. 这些枚举常量,不会因为我们写了sun就自动代表着"星期天",它只是一个符号,究

  • 枚举的用法详细总结

    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_

  • C++枚举类型用法总结(枚举字符常量代替常量)

    C++枚举类型enum表示枚举,通常用于定义个新类型的字符常量,比如enum {January,February,March}.枚举类型的作用域一般是整个文件或者类内.当枚举类型定义在文件开头时,则作用域是从定义位置开始往后(不包括函数内定义):当枚举类型在类内定义时,则作用域为整个类内.在类内的头文件定义和初始化枚举类型,当实例这个类的对象时,枚举类型不会占用空间,只是包含一个字符常量而已. 枚举类型的定义可以在整个文件夹,也可以在类内.当在整个文件夹时,所有枚举量不能有相同的.当在类内时,不

  • Go语言基础枚举的用法及示例详解

    目录 概述 一.普通枚举 二.自增枚举 注意 代码 概述 将变量的值一一列举出来,变量只限于列举出来的值的范围内取值 Go语言中没有枚举这种数据类型的,但是可以使用const配合iota模式来实现 一.普通枚举 const ( cpp = 0 java = 1 python = 2 golang = 3 ) 二.自增枚举 iota只能在常量的表达式中使用 fmt.Println(iota) //undefined: iota 它默认开始值是0,const中每增加一行加1 const ( a =

  • Python torch.onnx.export用法详细介绍

    目录 函数原型 参数介绍 mode (torch.nn.Module, torch.jit.ScriptModule or torch.jit.ScriptFunction) args (tuple or torch.Tensor) f export_params (bool, default True) verbose (bool, default False) training (enum, default TrainingMode.EVAL) input_names (list of st

  • nginx命令参数用法详细介绍

    nginx命令参数用法详细介绍 nginx命令:启动nginx 在Windows上安装好nginx后,我们需要启动nginx服务,启动nginx服务的命令行操作主要有两种方式,即 C:/nginx-0.8.53>nginx.exe 或者 C:/nginx-0.8.53>start nginx 启动nginx命令说明:需要注意,由于nginx默认端口也是80端口,如果此时你的机器上开启了Apache或者IIS服务,切忌在启动nginx之前务必关闭IIS或Apache服务,否则nginx启动命令不

  • PHP中error_reporting函数用法详细介绍

    PHP中error_reporting函数用法详细介绍 PHP中对错误的处理会用到error_reporting函数,看到最多的是error_reporting(E_ALL ^ E_NOTICE),这个是什么意思呢?下面我们具体分析error_reporting函数. 定义用法 error_reporting() 设置 PHP 的报错级别并返回当前级别. 语法 error_reporting(report_level) 如果参数 report_level 未指定,当前报错级别将被返回.下面几项是

  • Java多线程的用法详细介绍

    Java多线程的用法详细介绍 最全面的Java多线程用法解析,如果你对Java的多线程机制并没有深入的研究,那么本文可以帮助你更透彻地理解Java多线程的原理以及使用方法. 1.创建线程 在Java中创建线程有两种方法:使用Thread类和使用Runnable接口.在使用Runnable接口时需要建立一个Thread实例.因此,无论是通过Thread类还是Runnable接口建立线程,都必须建立Thread类或它的子类的实例.Thread构造函数: public Thread( ); publi

  • Java枚举类用法实例

    本文实例讲述了Java枚举类用法.分享给大家供大家参考.具体如下: package com.school.stereotype; /** * 活动枚举类型 * @author QiXuan.Chen */ public enum EventStatus { /** * 未发布. */ DRAFT("DRAFT", "未发布"), /** * 已发布. */ PUBLISHED("PUBLISHED", "已发布"); /**

  • Spring中@Transactional用法详细介绍

    Spring中@Transactional用法详细介绍 引言: 在spring中@Transactional提供一种控制事务管理的快捷手段,但是很多人都只是@Transactional简单使用,并未深入了解,其各个配置项的使用方法,本文将深入讲解各个配置项的使用. 1.  @Transactional的定义 Spring中的@Transactional基于动态代理的机制,提供了一种透明的事务管理机制,方便快捷解决在开发中碰到的问题.在现实中,实际的问题往往比我们预期的要复杂很多,这就要求对@Tr

  • Python进阶之高级用法详细总结

    一.Lambda表达式 Lambda表达式又被称之为匿名函数 格式 lambda 参数列表:函数体 def add(x,y): return x+y print(add(3,4)) #上面的函数可以写成Lambda函数 add_lambda=lambda x,y:x+y add_lambda(3,4) 二.map函数 函数就是有输入和输出,map的输入和输出对应关系如下图所示: 就是要把一个可迭代的对象按某个规则映射到新的对象上. 因此map函数要有两个参数,一个是映射规则,一个是可迭代对象.

随机推荐