C++11 强类型枚举
1.传统枚举类型的缺陷
枚举类型是C/C++中用户自定义的构造类型,它是由用户定义的若干枚举常量的集合。枚举值对应整型数值,默认从 0 开始。比如定义一个描述性别的枚举类型。
enum Gender{Male,Female};
其中枚举值 Male 被编译器默认赋值为 0,Female 赋值为 1。传统枚举类型在设计上会存在以下几个问题。
(1)同作用域同名枚举值会报重定义错误。传统 C++ 中枚举常量被暴漏在同一层作用域中,如果同一作用域下有两个不同的枚举类型,但含有同名的枚举常量也是会报编译错误的,比如:
enum Fruits{Apple,Tomato,Orange};
enum Vegetables{Cucumber,Tomato,Pepper}; //编译报Tomato重定义错误
其中水果和蔬菜两个枚举类型中包含同名的Tomato枚举常量会导致编译错误。因为enum则是非强作用域类型,枚举常量可以直接访问,这种访问方式与C++中具名的namespace、class/struct以及union必须通过"名字::成员名"的访问方式大相径庭。
(2)由于枚举类型被设计为常量数值的“别名”,所以枚举常量总是可以被隐式转换为整型,且用户无法为枚举常量定义类型。
(3)枚举常量占用存储空间以及符号性不确定。C++ 标准规定 C++ 枚举所基于的“基础类型”是由编译器来具体实现,这会导致枚举类型成员的基本类型存在不确定性问题,尤其是符号性问题。考察如下示例:
enum A{A1=1,A2=2,ABig=0xFFFFFFFFU};
enum B{B1=1,B2=2,BBig=0xFFFFFFFFFUL};int main()
{cout<<sizeof(A1)<<endl; //4cout<<ABig<<endl; //4294967295cout<<sizeof(B1)<<endl; //8cout<<BBig<<endl; //68719476735
}
以上输出结果是在Linux平台下使用 g++ 编译输出的结果,在 VC++(VS2017)中的输出结果分别是 4、-1、4 和 -1。可见不同编译器对枚举常量的整型类型的宽度和符号有着不同的实现。GNU C++ 会根据枚举数值的类型使用不同宽度和符号的整型,VC++ 则始终以有符号 int 来表示枚举常量。
为了解决以上传统枚举类型的缺陷,C++11 引入了强类型枚举解决了这些问题。
2.强类型枚举
非强作用域类型,允许隐式转换为整型,枚举常量占用存储空间以及符号性的不确定,都是枚举类缺点。针对这些缺点,C++11 引入了一种新的枚举类型——强类型枚举(strong-typed enum)。
强类型枚举使用enum class语法来声明:
enum class Enumeration{VAL1,VAL2,VAL3=100,VAL4};
强类型枚举具有如下几个优点:
(1)强作用域,强类型枚举成员的名称不会被输出到其父作用域,所以不同枚举类型定义同名枚举成员编译不会报重定义错误。进而使用枚举类型的枚举成员时,必须指明所属范围,比如Enum::VAL1,而单独的VAL1则不再具有意义;
(2)转换限制,强类型枚举成员的值不可以与整型发生隐式相互转换。比如比如Enumeration::VAL4==10;会触发编译错误;
(3)可以指定底层类型。强类型枚举默认的底层类型是int,但也可以显示地指定底层类型。具体方法是在枚举名称后面加上":type",其中type可以是除wchar_t以外的任何整型。比如:
enum class Type:char{Low,Middle,High};
注意:
(1)声明强类型枚举的时候,既可以使用关键字enum class,也可以使用enum struct。事实上,enum struct与enum class在语法上没有任何区别。
(2)由于强类型枚举是强类型作用域的,故匿名的enum class可能什么都做不了,如下代码会报编译错误:
enum class{General,Light,Medium,Heavy}weapon;
int main()
{weapon=Medium; //编译出错bool b=weapon == weapon::Medium; //编译出错return 0;
}
当然对于匿名强类型枚举我们还是可以使用decltype来获得其类型并进而使用,但是这样做可能违背强类型枚举进行匿名的初衷。
3.C++11对传统枚举类型的扩展
传统枚举类型为了配合C++11引入的强类型枚举,C++11对传统枚举类型进行了扩展。
(1)底层的基本类型可以在枚举名称后加上":type",其中type可以是除wchar_t以外的任何整型,比如:
enum Type:char{Low,Middle,High};
(2)C++11 中,枚举类型的成员可以在枚举类型的作用域内有效。比如:
enum Type{Low, Middle, High };
Type type1 = Middle;
Type type2 = Type::Middle;
其中Middle与Type::Middle都是合法的使用形式。
参考文献
[1] 深入理解C++11[M].C5.1强类型枚举.P155-161
[2] C++11强类型枚举——枚举类
C++11 强类型枚举相关推荐
- C++11强类型枚举,override/final
C++11(一)开篇 这个系列主要介绍C++11的一些新的特性,C++11问世至今已经有将近十年了.但是许多公司仍然停留在C++98上.之前在部门分享过C++11的知识,在这里分享给有需要的人. C+ ...
- C++11 强类型枚举和普通枚举
文章目录 **1.传统枚举类型的缺陷** **2.强类型枚举** **3.C++11对传统枚举类型的扩展** 1.传统枚举类型的缺陷 枚举类型是C/C++中用户自定义的构造类型,它是由用户定义的若干枚 ...
- 蓝桥备赛第一周2021.1.11 递归 枚举 位运算
文章目录 递归实现指数型枚举 递归指数型枚举 方法1:肯定是2^n行,所以直接就是上一个动态m从0到n加一堆空行 方法2:以最新的值为n为结束,遇到为0的不输出,用完要恢复为0 递归实现排列型枚举 非 ...
- C++11实战——多线程的日志类
C++11实战--多线程的日志类 C++标准库的std::cout和std::ofstream重载了operator<<,单线程使用非常简单.但由于其并非线程安全,在多线程中使用则需要自己 ...
- 现代C++教程1X读书笔记
C++1X(11.14.17)各版本变化 传统C++指的是C++1X以前 有些特性变化高版本不一定向下兼容 可用性强化 常量 nullptr 传统C++:只支持NULL C++ 11:引入nullpt ...
- 使用Clang作为编译器 —— Clang 语言扩展
1. 介绍 本文档描述了 Clang 提供的语言扩展.除了这里列出的语言扩展之外,Clang 还旨在支持广泛的 GCC 扩展.有关这些扩展的更多信息,请参阅 GCC手册. 2. 特性检查宏 语言扩展可 ...
- c++枚举类型(二) c++11 枚举类
C++11 标准中引入了"枚举类"(enum class),可以较好地解决如下问题. 新的enum的作用域不在是全局的 不能隐式转换成其他类型 /*** @brief 上述如果 u ...
- c++ enum 给定类型_C++11作用域内枚举enum
在C++11之前的枚举(enum),是没有办法两个枚举(enum)内有相同枚举名的.如果还不知道C++中枚举(enum)是什么,可以看这篇:枚举enum 如:苹果和桔子都有大,中,小.写个代码来说明下 ...
- c++11的10个新特性
C++11标准由国际标准化组织(ISO)和国际电工委员会(IEC)旗下的C++标准委员会(ISO/IEC JTC1/SC22/WG21)于2011年8月12日公布[2] ,并于2011年9月出版.2 ...
最新文章
- emacs python开发环境_配置Emacs下的Python开发环境
- 11.2.0.2 HAIP
- godot python_我的godot开发环境调教记录分享
- 趣味物理中的计算机科学,【趣味物理】10个有趣的科学实验,揭示物理原理。...
- 练习1,从文件到数据库
- C++、QT的物业管理系统
- 2020软考信息系统项目管理师-案例分析真题解析视频课程-任铄(小任老师)-专题视频课程...
- 关闭Dynamipsgui的自动更新
- 《Linux系统最佳实践工具:命令行技术》新书抢先看
- 【软件测试】如何定位web前后台的BUG
- [Unix下C/C++开发] unix编程书籍推荐
- 游戏制作之路(54)自制天空盒
- 【测试】软件测试岗位与职业发展
- bugku_逆向_游戏过关
- websocket + tls + cdn 断流严重问题解决方法
- UltraISO软碟通制作U盘启动盘
- 2016年度星级专利代理机构名单排名
- 大话设计模式——工厂模式
- 麻辣GIS源码的github下载与调试
- 数据库MySQL(一) 常用查询语句