C++ - 枚举 (Enum)
在 C++ 中,枚举 (或 enum) 是一种用户定义的数据类型,它由一组命名的整型常量组成。
创建(声明)枚举类型
要创建枚举 (enum),请使用 enum 关键字,后接枚举名称以及用花括号括起来的命名值列表。
语法
以下是创建枚举的语法 -
enum enumName {
Enumerator_value1,
Enumerator_value2,
Enumerator_value3,
// So on
};
此处,
- enum 是声明枚举类型的关键字。
- enumName 是枚举的名称。
- Enumerator_Value1、Enumerator_Value1、Enumerator_Value1 等是整型常量。
访问枚举
您可以通过在 int main() 函数体内使用变量名声明枚举(enum)并根据需要调用它来访问它。
语法
以下是访问或调用枚举的语法:
enum enumName {
Enumerator_value1,
Enumerator_value2,
Enumerator_value3,
// So on
};
// 创建变量并赋值
enumName enam_var = value;
此处,
- enumName 是枚举声明的变量名。
- variableName 是枚举器(枚举内定义的值)的变量名。
C++ 枚举示例
在下面的示例中,我们声明了一个枚举类型,声明了一个枚举的变量/对象,并访问了枚举常量。请考虑以下示例 -
#include <iostream>
using namespace std;
// 定义一个名为 Day 的枚举,表示一周中的某几天
enum Day {
Sunday, // 0
Monday, // 1
Tuesday, // 2
Wednesday, // 3
Thursday, // 4
Friday = 45, // 45
Saturday // 46
};
int main() {
// 声明一个日期变量
Day get1 = Wednesday;
cout<<get1<<endl;
cout<<Saturday<<endl;
return 0;
}
输出
3 46
说明
在上述代码中,默认情况下,每周的每一天都被显式地赋予一个唯一的整数值,范围从 0 到 6,表示一周中的所有天数。但是,如果我们显式地将值 45 赋给星期五,枚举属性将使序列从该特定点继续,因此剩余的星期五和星期六的值将分别变为 45 和 46,从而完成后续的序列。
C++ 枚举的类型
C++ 中通常有两种类型的枚举 -
1. 无作用域枚举
无作用域枚举是 C++ 中传统的枚举形式。它们使用 enum 关键字定义,并在其作用域内声明枚举器名称。由于枚举器名称被添加到周围作用域,如果不仔细管理,可能会导致名称冲突,因此它可以直接在代码中使用它,就像一组代表特定数字的标签一样。
它会自动从零开始分配整数值,除非明确指定,并且可以隐式转换为整数。
示例
#include <iostream>
using namespace std;
enum RGB {
Red, // 0
Green, // 1
Blue // 2
};
void printColor(RGB color) {
switch (color) {
case Red: cout << "Color is Red"; break;
case Green: cout << "Color is Green"; break;
case Blue: cout << "Color is Blue"; break;
}
}
int main() {
RGB myColor = Red; // 这里无需指定枚举名称
int value = myColor; // 隐式转换为 int
cout << "Integer value: " << value << endl; // Outputs: 0
printColor(myColor); // 输出:颜色为红色
return 0;
}
输出
Integer value: 0 Color is Red
2. 作用域枚举(枚举类)
C++11 中引入了作用域枚举,使用枚举类进行定义。它们提供更好的类型安全性,并且更加条理化,其枚举器名称限定在枚举范围内。这意味着它们的标签会被保留在特定的组中,因此在使用它们时需要提及组名。这有助于避免在不同组中使用相似标签时产生混淆。
枚举器名称限定在枚举类型范围内,这意味着您必须使用枚举名称来访问它们。它们不会隐式转换为整数,这有助于增强类型安全性。
示例
#include <iostream>
using namespace std;
enum class Color {
Red, // Implicitly 0
Green, // Implicitly 1
Blue // Implicitly 2
};
// 用法
int main() {
Color myColor = Color::Red; // 必须使用枚举名称
// int value = myColor; // 错误:无隐式转换
// 如果需要,则显式转换为 int
int value = static_cast<int>(myColor); // value = 0
cout << "Integer value: " << value << endl; // Outputs: 0
return 0;
}
输出
Integer value: 0
作用域 Vs.无作用域枚举
| 特性 | 无作用域枚举 | 有作用域枚举(枚举类) |
|---|---|---|
| 枚举器的作用域 | 全局作用域 | 枚举类型内的作用域 |
| 名称冲突 | 可能 | 已避免 |
| 隐式转换 | 是 | 否 |
| 类型安全性 | 更少 | 更多 |
| 底层类型 | 默认为 int | 可指定自定义类型 |
比较枚举值
枚举值的比较方式与整数比较类似。请参考以下示例 -
示例
#include <iostream>
using namespace std;
enum class Color {
Red,
Green,
Blue
};
int main() {
Color myColor = Color::Green;
if (myColor == Color::Green) {
cout << "The color is green!" << endl;
} else {
cout << "The color is not green." << endl;
}
return 0;
}
输出
The color is green!
枚举作为函数参数
您可以将枚举作为参数传递给函数。要将枚举作为函数参数传递,您需要在其实例中指定枚举名称。
示例
在以下示例中,我们将枚举作为参数传递 -
#include <iostream>
using namespace std;
enum class Color {
Red,
Green,
Blue
};
// 以枚举作为参数的函数
void printColor(Color color) {
switch (color) {
case Color::Red:
cout << "Red" << endl;
break;
case Color::Green:
cout << "Green" << endl;
break;
case Color::Blue:
cout << "Blue" << endl;
break;
}
}
int main() {
Color myColor = Color::Blue;
printColor(myColor);
return 0;
}
输出
Blue
枚举的常见用例
以下是枚举的一些常见用例 -
1. 状态管理
enum class GameState {
MainMenu,
Playing,
Paused,
GameOver
};
2. 配置选项
enum class LogLevel {
Info,
Warning,
Error,
Debug
};
3. 命令类型
enum class Command {
Start,
Stop,
Pause,
Resume
};
4. 方向和运动
enum class Direction {
Up,
Down,
Left,
Right
};
使用枚举的好处
- 提高可读性和维护性 − 枚举为值提供有意义的名称,使代码更清晰、更易于理解和维护。
- 类型安全和命名空间管理 − C++ 中的枚举会限制赋值,尤其是使用作用域枚举时,这可以减少错误并避免名称冲突。
- 有序的代码结构 − 枚举通过对相关常量进行分组来增强代码组织性,从而提高代码可读性、增强类型安全性、创建更清晰的函数接口并简化重构。
- 增强的功能 − 枚举可以与 switch 语句顺畅配合,并允许通过赋值显式控制底层类型。
枚举的局限性
尽管枚举有很多优点,但它仍然存在以下一些局限性−
- 类型安全问题 − 无作用域的枚举可能导致名称冲突,并允许隐式转换为整数,这会增加出错的风险。
- 功能受限 − 枚举具有一组固定的值,并且缺少无法在运行时扩展的成员函数。
- 调试困难 − 调试器可能会将枚举值显示为整数,这使得解释其含义变得更加困难。

