一、枚举类型的概念
在实际编程中,经常会遇到变量的取值被限定在一个有限的、确定的范围内的情况。例如:
- 一场比赛的结果只有胜、负、平、取消四种状态
- 一个袋子里的球只有红、黄、蓝、白、黑五种颜色
- 一个星期只有星期一、星期二至星期日七天
如果使用 int 或 char 来表示这些值(比如用 0~6 表示星期几),编译器无法阻止程序将 8 这样的非法值赋给变量,存在安全隐患。
C++ 的枚举类型(enum)就是专门为解决这类问题而设计的。它将变量所有可能的取值范围一一列举出来,此后该类型的变量只能取列举出的值,增强了代码的可读性和类型安全性。
二、枚举类型的声明形式
enum 枚举类型名 {枚举元素列表};
示例:
enum Weekday {SUN, MON, TUE, WED, THU, FRI, SAT};
enum GameResult {WIN, LOSE, DRAW, CANCEL};
enum BallColor {RED, YELLOW, BLUE, WHITE, BLACK};
三、枚举元素的值
1. 默认赋值规则
枚举元素在声明时如果没有显式指定值,编译器会自动从 0 开始依次赋值。
enum Weekday {SUN, MON, TUE, WED, THU, FRI, SAT};
| 枚举元素 | 默认值 |
|---|---|
| SUN | 0 |
| MON | 1 |
| TUE | 2 |
| WED | 3 |
| THU | 4 |
| FRI | 5 |
| SAT | 6 |
2. 显式指定值
可以在声明时手动为枚举元素指定值,后面未指定的元素依次在前一个值的基础上加 1。
enum Weekday {SUN = 7, MON = 1, TUE, WED, THU, FRI, SAT};
| 枚举元素 | 值 |
|---|---|
| SUN | 7 |
| MON | 1 |
| TUE | 2 |
| WED | 3 |
| THU | 4 |
| FRI | 5 |
| SAT | 6 |
3. 注意事项
- 枚举元素的值在编译期确定,不能对枚举元素进行赋值操作。例如
SUN = 0;是不合法的。 - 多个枚举元素可以具有相同的值。
- 枚举元素的作用域与枚举类型本身的作用域一致。
四、枚举变量的定义与使用
1. 定义枚举变量
Weekday today; // 定义 Weekday 类型的变量
GameResult result; // 定义 GameResult 类型的变量Code language: JavaScript (javascript)
也可以在声明枚举类型的同时定义变量:
enum Weekday {SUN, MON, TUE, WED, THU, FRI, SAT} today, tomorrow;
2. 枚举变量的赋值
枚举变量只能被赋值为该枚举类型中定义的枚举元素,不能直接赋值为整数。
today = MON; // 正确
// today = 1; // 错误:不能将 int 直接赋给枚举变量Code language: JavaScript (javascript)
如果确实需要将整数转换为枚举值,必须进行强制类型转换:
today = Weekday(3); // 正确:将 3 强制转换为 Weekday 类型,等价于 WEDCode language: JavaScript (javascript)
3. 枚举值的关系运算
枚举值可以进行关系运算(比较大小),比较时实际比较的是它们对应的整数值。
if (today == WED) { ... }
if (MON < FRI) { ... } // 比较的是 1 < 5Code language: JavaScript (javascript)
五、代码示例
以下代码演示了枚举类型的各种用法:
#include <iostream>
using namespace std;
int main()
{
// 示例1:基本枚举类型
enum Weekday {SUN, MON, TUE, WED, THU, FRI, SAT};
Weekday today = WED;
cout << "today = " << today << endl; // 输出 3
// 示例2:显式指定枚举值
enum Weekday2 {SUNDAY = 7, MONDAY = 1, TUESDAY, WEDNESDAY, THURSDAY, FRIDAY, SATURDAY};
Weekday2 d = SUNDAY;
cout << "d = " << d << endl; // 输出 7
// 示例3:枚举变量的赋值与输出
Weekday day1 = MON;
Weekday day2 = FRI;
cout << "day1 = " << day1 << ", day2 = " << day2 << endl; // 输出 1 和 5
// 示例4:枚举的关系运算
if (day1 < day2)
cout << "MON comes before FRI" << endl;
// 示例5:枚举在 switch 语句中的使用
Weekday d2 = SAT;
switch (d2)
{
case MON: cout << "Monday" << endl; break;
case TUE: cout << "Tuesday" << endl; break;
case WED: cout << "Wednesday" << endl; break;
case THU: cout << "Thursday" << endl; break;
case FRI: cout << "Friday" << endl; break;
case SAT: cout << "Saturday" << endl; break;
case SUN: cout << "Sunday" << endl; break;
}
// 示例6:整数强制转换为枚举
int n = 4;
Weekday d3 = Weekday(n); // 强制转换,n=4 对应 THU
cout << "d3 = " << d3 << endl;
// 示例7:比赛结果枚举
enum GameResult {WIN, LOSE, DRAW, CANCEL};
GameResult r = WIN;
cout << "Game result: " << r << endl; // 输出 0
// 示例8:枚举元素的值
enum Color {RED, GREEN, BLUE = 10, YELLOW, CYAN = 15, MAGENTA};
cout << "RED=" << RED << " GREEN=" << GREEN << " BLUE=" << BLUE;
cout << " YELLOW=" << YELLOW << " CYAN=" << CYAN << " MAGENTA=" << MAGENTA << endl;
// 输出:RED=0 GREEN=1 BLUE=10 YELLOW=11 CYAN=15 MAGENTA=16
// 示例9:枚举作为循环变量
for (Weekday w = SUN; w <= SAT; w = Weekday(w + 1))
{
cout << w << " ";
}
cout << endl;
// 示例10:声明时定义变量
enum Season {SPRING, SUMMER, AUTUMN, WINTER} current = AUTUMN;
cout << "current season = " << current << endl; // 输出 2
return 0;
}Code language: PHP (php)
六、注意事项
- 枚举元素不是字符串,不能直接用
cout输出其名称。输出时得到的是对应的整数值。如需输出名称,需借助 switch 语句或映射表。 - 枚举变量的取值范围理论上可以存储任意整数,但只有赋值为枚举元素或经过强制转换的值才有明确意义。
- 枚举类型占用内存大小通常等于 int 的大小,但具体由编译器决定。
- 枚举元素之间不能重名。如果不同枚举类型中有相同名称的元素,需通过枚举类型名区分(在 C++11 强类型枚举 enum class 中解决)。
- 不能直接将整数赋给枚举变量,也不能直接将枚举变量赋给整数类型变量(需要强制转换)。但枚举变量可以隐式转换为整数参与运算。
七、C++11 强类型枚举(enum class)
C++11 引入了强类型枚举(枚举类),解决了传统枚举的命名冲突和隐式转换问题:
enum class Weekday {SUN, MON, TUE, WED, THU, FRI, SAT};
Weekday d = Weekday::MON; // 必须用作用域运算符
// int x = d; // 错误:不能隐式转换
int x = static_cast<int>(d); // 正确:显式转换Code language: PHP (php)
强类型枚举的优点:
| 特性 | 传统 enum | enum class |
|---|---|---|
| 作用域 | 枚举元素暴露在枚举所在作用域 | 枚举元素限定在枚举类型内 |
| 隐式转换 | 可隐式转换为 int | 不能隐式转换为 int |
| 底层类型 | 由编译器决定 | 可显式指定,如 enum class Color : char { … } |
Previous: 自定义数据类型-typedef
Next: 练习一下-枚举