普通枚举

对局状态、配置档位这类数据只取有限的几个值。用 int 编号表达它们时,任何整数都是合法赋值,类型系统帮不上忙。从 C 语言继承的普通 enum 迈出了第一步,但留下作用域和转换两个缺口,本章把它们看清楚,下一章再引入 enum class 补上。

enum 的边界

普通 enum 沿袭 C 语言的规则:枚举名直接进入外层作用域,并且能向整数隐式转换:

片段:普通 enum 的两个问题
enum Color { Red, Green };
int value = Red;  // 枚举值隐式转换成 int,编译器不报错

隐式转换让“误赋一个无关整数”通过编译,外层作用域则让 Red 这类短名字容易与其它名字冲突。两个问题同根同源:枚举值在编译器眼里仍然是整数,没有自己的类型边界。

类型边界

想要的安全性质:取值只限于列出的几个名字,赋错值编译失败,枚举名不污染外层作用域。普通 enum 给不了这些,enum class 能给全:枚举值限定在类型名内,与整数切断隐式转换。

自测问题

先不要展开答案,试着自己把回答完整说出来,再展开对照。说不出来的部分,回到对应小节对照正文。

  1. 普通 enum 有哪两个问题?

    查看答案

    枚举名直接进入外层作用域,短名字容易冲突。枚举值能向整数隐式转换,误赋无关整数也能通过编译。

  2. 为什么说这两个问题同根同源?

    查看答案

    两者都源于普通 enum 的枚举值在类型层面仍是整数:编译器不做类型边界检查,作用域规则也停留在 C 语言的整型常量时代。

本章回顾

你现在能识别普通 enum 的作用域泄漏与隐式转换两个问题。下一章用 enum class 补上类型边界,并给出底层类型、成员注释与按值传参的写法。