3.7  枚举类型

除了之前我们介绍的数值数据和文字数据之外,在现实世界中,常常还会遇到这样一类数据:一道单选题的答案只能是A、B、C、D四个选项中的某一个;红绿灯的颜色只能是红色,绿色和黄色中的某一种;一个人的性别只能是男性或者女性。这种数据都只有有限的几种可能值,其值也只能是这个范围内的某一个。为了抽象和表达这种特殊数据,C++提供了枚举机制。

使用C++的枚举机制,我们可以通过列举某种数据的所有可能值来定义一种新的数据类型,这种数据类型通常被称为枚举类型。反过来,当使用枚举类型来定义变量时,这个变量的取值也就限定在了枚举类型所列举出的可能取值范围内。定义一个枚举类型的语法格式如下:

  1. enum 枚举类型名
  2. {
  3. // 可能的枚举值列表
  4. }; // 注意,这里必须以分号表示结束

其中,enum是定义枚举类型的关键字;枚举类型名是所要创建的新数据类型的名字,完成枚举类型的定义后,我们可以用它作为数据类型来定义变量;而在枚举类型的定义中,可以逐个列出这个枚举类型的所有可能值。例如,可以将描述交通灯颜色的数据抽象成一个枚举类型:

  1. // 交通灯颜色
  2. enum TrafficLight
  3. {
  4. RED, // 红
  5. GERRN, // 绿
  6. YELLOW // 黄
  7. };

有了这样的TrafficLight枚举类型的定义,我们就可以用它做为数据类型来定义一个变量,用以表示交通灯的颜色:

  1. // 定义一个变量light表示交通灯的颜色
  2. // 将枚举值RED赋值给它,表示当前交通灯是红色
  3. TrafficLight light = RED;

因为枚举类型所表达数据的特殊性,使我们在应用枚举类型时需要注意以下几点。

1. 枚举类型中的枚举值有对应的默认整数值

在本质上,枚举类型数据是一个整型数值,每个枚举类型的可选值其实是一个整数值。在默认情况下,第一个枚举值对应的是整数值0,第二个是1,以此类推。例如,上面TrafficLight枚举类型中的RED可选值其实就是整数值0,而GREEN就是1,YELLOW自然就是2了。如果认为枚举值的默认对应整数值不合适。比如,在某些情况下,我们希望某个枚举值拥有特殊的整数值以表示特殊含义,这时也可以在定义的时候另行指定各个枚举值对应的整数值。例如:

  1. // 另行指定各个枚举值对应的整数值
  2. enum TrafficLight
  3. {
  4. RED = , // 指定对应的整数值,不再是从0开始
  5. GERRN, //
  6. YELLOW = // 指定对应的整数值为0,表示特殊含义
  7. };

经过人为地指定枚举值对应的数值后,RED对应的整数值就变为了1,其后的GREEN增加一个自然也就随之而变为2,而对于最后的YELLOW,因为其特殊意义,我们又人为地将其指定为0。

2. 枚举类型变量的赋值

如果变量是枚举类型,那就只能使用这种枚举类型的某个枚举值对其进行赋值。例如:

  1. // 红灯
  2. TrafficLight light = RED;
  3. // 变为绿灯
  4. light = GREEN;
  5. // 如果是用枚举值之外的数据对其进行赋值,会导致编译错误
  6. // 即使这个值是某个枚举值对应的整数值
  7. light = ;

换句话说,如果想把某个变量的取值限定在某几个可选值范围之内,则可以把这个变量定义为枚举类型变量。

3. 枚举值是常量,定义后不可改变其对应整数值

在定义枚举类型时,就已经完成了枚举值的定义,其对应的数值不是默认数值就是给定的特殊数值。定义完成后,各个枚举值的数值就成为了常量,要按照常量来处理,不能对其进行赋值。也就是说,不能在完成定义后再改变其中某个枚举值对应的整数值。例如,下面的语句是非法的:

  1. RED = ; // 尝试改变枚举值,导致编译错误

枚举类型中的枚举值实质是一些整型常量。在上面的例子中,完全可以使用3个整型常量来表示交通灯的三种颜色。但是,枚举类型允许我们用描述性的名称来表示某个有限范围内的整数值,而不是直接使用含义模糊的整数值,这有助于确保给变量指定合法的期望值,同时这也使得我们的代码意义明确,更具可读性,也更易于维护。所以,如果要表达的数据“只有有限的几种可能值”时,我们应该优先选择使用枚举类型。

知道更多:带作用域的枚举类

虽然枚举类型可以方便地定义某个范围内的枚举值。但是,因为传统的枚举类型在本质上是一个int类型的整数,因此在使用中,也常常存在各种各样的问题。例如,传统枚举类型的所有枚举值在其定义后的代码范围内都是可以使用的,而这可能会造成名字污染,使得其后的代码就不能再把这个枚举值名字用作其他用途;不可以指定枚举类型的底层数据类型,这可能会浪费内存资源,同时也使得枚举类型不可以进行前向声明。所谓前向声明,就是在某个元素(函数或者类)尚未定义的时候,为了提前使用它而进行的声明,向编译器表明源文件中有这个元素的定义,现在就可以放心大胆地使用,而具体的定义会在稍后给出。正是为了解决传统枚举类型所存在的这些问题,C++11提出了新的具有作用域,并可以指定底层数据类型的枚举类。

定义枚举类的语法形式跟定义一个传统的枚举类型的语法形式十分相似:

  1. enum class 枚举类名:数据类型
  2. {
  3. // 可能的枚举值列表
  4. };

枚举类的定义以“enum class”开始,后面跟上枚举类名,其后还可以用冒号“:”指定枚举类的底层数据类型。枚举类的底层数据类型必须是有符号或无符号的整型数,如果不指定,其默认的数据类型是int类型。例如:

  1. // 定义一个枚举类TrafficLight,
  2. // 并指定其底层数据类型为char类型
  3. enum class TrafficLight : char
  4. {
  5. RED = , // 红
  6. GERRN, // 绿
  7. YELLOW // 黄
  8. };

虽然枚举类的定义同传统的枚举类型的定义十分相似,但是因为两者内在机制的不同,他们已经是完全不同的两个概念。枚举类具有作用域,其枚举值只在其作用域内可见,这就很好地解决了枚举值可能引起的名字污染问题。例如:

  1. // 枚举值RED属于TrafficLight作用域
  2. // 所以我们必须在其前面加上TrafficLight才能访问
  3. TrafficLight light = TrafficLight::RED;
  4. // 定义一个名为RED的变量,虽然与枚举值RED同名,
  5. // 但是两者不会产生冲突,也就是枚举值RED的定义
  6. // 没有引起名字污染
  7. bool RED = true;

除了解决名字污染问题之外,因为可以指定枚举的底层数据类型,这使得前向声明成为可能,同时,根据枚举值的多少,选择合适的底层数据类型,也可以在一定程度上避免资源的浪费。例如:

  1. // 使用前的前向声明,只是声明了枚举类的名字,
  2. // 没有定义具体的枚举值
  3. enum class TrafficLight : char;
  4. // 使用前向声明的枚举类
  5. void foo(TrafficLight* light)
  6. {
  7. // ...
  8. }
  9.  
  10. // …
  11.  
  12. // 补充完成枚举类的定义
  13. enum class TrafficLight : char
  14. {
  15. RED = , // 红
  16. // …
  17. };

在这段代码中,我们完成枚举类TrafficLight枚举类的前向声明后,就可以直接使用了。而在最后,我们只需要补充上它的具体定义即可。另外,我们在这里指定了枚举值的底层数据类型为char,这要比默认的int更加节省资源。

从上面的例子我们可以看到,枚举类的使用,很好地解决了传统的枚举类型在使用中所遇到的各种问题,所以,在以后的编程实践中,我们应该优先选择使用枚举类。

你好,C++(13)这道单选题的答案是A、B、C还是D?3.7 枚举类型的更多相关文章

  1. 某软件大赛C#版考题整理——【单选题】

    多选题:http://www.cnblogs.com/zxlovenet/p/3525849.html 编程题:http://www.cnblogs.com/zxlovenet/p/3525854.h ...

  2. h5 页面 实现单选题,多选题功能。

    效果图: 项目要求: 1:实现单选题和多选题区分 (这个根据后端传来的数据判断 ) 2 单选选中效果 和  多选选中效果(利用input 和label ) 3.答题成功与失败 分单选和多选的情况    ...

  3. 华为云Stack首席架构师:打造“称手”的数字化工具,答好政企IT数字化转型这道必选题

    摘要:数字化转型是一号位工程,数字化的工具本身就是企业的核心竞争力. 本文分享自华为云社区<华为云Stack首席架构师:打造"称手"的数字化工具,答好政企IT数字化转型这道必 ...

  4. html5--3.13 表单的新增属性

    html5--3.13 表单的新增属性 学习要点 掌握表单新增属性的使用 HTML5新增表单属性 之前课程中已经接触过的新增属性:autocomplete属性/autofocus属性/list属性/m ...

  5. K2 BPM_“选BPM还是RPA?”,这不是一道单选题_全业务流程管理专家

    在我们和企业讨论流程自动化的时候,经常会被问到一个问题,“公司目前正在调研市面上的业务流程自动化产品,我们已经把选择范围缩小到了BPM和RPA之间.我们应该怎么选择?BPM能做的好像RPA都能做到.” ...

  6. 用私有构造器或者枚举类型强化SingleTon(单例)属性

    单例(singleton)就是一个只实例化一次的类.使类成为单例可能会使它的测试变得困难,因为除非它实现了作为其类型的接口,否则不可能用模拟实现来代替这个单例.下面是几种实现单例的方法: 1.共有静态 ...

  7. Effective Java —— 用私有构造器或枚举类型强化单例属性

    本文参考 本篇文章参考自<Effective Java>第三版第三条"Enforce the singleton property with a private construc ...

  8. Django ORM 操作 必知必会13条 单表查询

    ORM 操作 必知必会13条 import os # if __name__ == '__main__': # 当前文件下执行 os.environ.setdefault('DJANGO_SETTIN ...

  9. Nodejs in Visual Studio Code 13.构建单页应用Scrat示例挖一挖

    1.开始 Scrat作者说要搞个很碉堡的示例,果然就搞出来了,如果要学习并使用Scrat,可以从官方示例开始,简直太方便了. 2.Scrat示例 目录 component_modules : 公共组件 ...

随机推荐

  1. UITextFiled自动补全输入,选中补全内容。NSRange和UITextRange的相互转换。-b

    有个需求就是 需要用户输入几位以后账号,可以根据本地存储的登录成功的账号,进行自动补全,并且补全内容为选中状态,不影响用户的新输入. 研究了一下,下面是完整的实现的方法. 补充个下载地址http:// ...

  2. Asp.net中request.QueryString与request.Params的区别 【转】

    Request.Form:获取以POST方式提交的数据(接收Form提交来的数据): Request.QueryString:获取地址栏参数(以GET方式提交的数据) Request:包含以上两种方式 ...

  3. 调用系统API还是很高效的,不必担心性能

    代码如下: void MainWindow::on_pushButton_2_clicked() { QTime total; total.start(); ; ; i<=*; i++) { Q ...

  4. flex4.6事件分派+组件+参数传递

    <?xml version="1.0" encoding="utf-8"?> <s:Application xmlns:fx="ht ...

  5. centos ppp拨号

    CentOS 6.4 电信ADSL 拨号连接的配置,亲测 .下载 rp-pppoe-3.8.tar.gz http://down1.chinaunix.net/distfiles/rp-pppoe-3 ...

  6. Makefile中的wildcard和patsubst

    makefile 里的函数跟它的变量很相似——使用的时候,你用一个 $ 符号跟开括号,函数名,空格后跟一列由逗号分隔的参数,最后用关括号结束.    例如,在 GNU Make 里有一个叫 'wild ...

  7. TF31003错误的解决办法

    TF31003错误的解决办法   在今天上午机器重新启动后,VS2012突然无法连接TFS2010了.在机器重新启动之前还使用正常.刚开始以为TFS出现了问题,不过其他小组同事使用却正常,问题应该在我 ...

  8. Number Transformation

    Description In this problem, you are given a pair of integers A and B. You can transform any integer ...

  9. HDOJ 1028 Ignatius and the Princess III(递推)

    Problem Description "Well, it seems the first problem is too easy. I will let you know how fool ...

  10. HDOJ 1098 Ignatius's puzzle

    Problem Description Ignatius is poor at math,he falls across a puzzle problem,so he has no choice bu ...