本周小贴士#86:带类的枚举

作为totw/86最初发表于2015年1月5日

由Bradley White (bww@google.com)创作

“显示类,…并显示字符。”——贝尔.布莱恩特

enumeration,简称enum,是一种可以容纳一组指定整数中的一个类型。此集合中的某些值可以命名,它们被称为枚举值。

无作用域枚举

C++程序员很熟悉这个概念,但在C++11之前,枚举有两个重大的缺陷:枚举的名称:

  • 在与枚举类型相同的作用域内,然后隐式转换为某种整形值。
    因此,使用C++98…
enum CursorDirection { kLeft, kRight, kUp, kDown };
CursorDirection d = kLeft; // 可行:作用域内的枚举器
int i = kRight;            // 可行:枚举器转换为整形

然而,…

// 错误:重新声明kLeft和kRight
enum PoliticalOrientation { kLeft, kCenter, kRight };

C++11以一种方式修改无作用域枚举的行为:枚举值对于枚举而言是局部的,但为了向后兼容,它会继续导出到枚举的作用域中。
因此,使用C++11…

CursorDirection d = CursorDirection::kLeft;  // 在C++11中可行
int i = CursorDirection::kRight;             // 可行:继续转换为整形

但PoliticalOrientation的声明依然将引起错误。

作用域枚举

已经观察到的隐式转换为整形是错误的来源,而枚举值与枚举在相同作用域造成的命名空间污染,会在大型且多库项目中引起问题。为了解决这些担忧,C++11引入了一个新的概念:作用域枚举。

在一个由关键字enum class引入的作用域枚举中,这些枚举值是:

  • 仅作为枚举(它们它们不会导出到枚举的作用域中)的局部变量,并且不会被隐式转换为整形。

因此,(注意额外的class关键字)…

enum class CursorDirection { kLeft, kRight, kUp, kDown };
CursorDirection d = kLeft;                    // 错误,kLeft不在这个作用域内
CursorDirection d2 = CursorDirection::kLeft;  // 可行
int i = CursorDirection::kRight;              // 错误:无法转换

和…

// 可行:kLeft和kRigh都是每个作用域枚举的局部变量
enum class PoliticalOrientation { kLeft, kCenter, kRight };

这些简单的更改消除了普通枚举的问题,因此在所有新代码中应该优先使用enum class。

使用作用域枚举确实意味着,如果你仍然想如此的转换(例如,当记录一个枚举值时,或在类似标志的枚举值上使用按位运算时),你必须显式转换为整形。使用std::has进行散列将继续工作(例如,std::unorderd_map<CursorDirection, int>)。

底层枚举类型

C++11还为两类枚举类型引入了指定底层类型的能力。以前枚举的底层整型类形是通过枚举值的符号和大小来确定的,但是我们现在能够明确指定了。例如,…

// 使用'int'作为CursorDirection的底层类型
enum class CursorDirection : int { kLeft, kRight, kUp, kDown };

因为这个枚举值的范围很小,并且如果我们希望在存储CursorDirection时避免浪费空间,那么我们可以指定char来代替。

// 使用'char'作为CursorDirection的底层类型
enum class CursorDirection : char { kLeft, kRight, kUp, kDown };

如果一个枚举值超过了底层类型的范围,那么编译器会报错。

结论

在新代码中优先使用enum class。你将减少命名空间污染,并且将避免在隐式转换中的错误。

enum class Parting { kSoLong, kFarewell, kAufWiedersehen, kAdieu };
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值