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 语句顺畅配合,并允许通过赋值显式控制底层类型。
枚举的局限性
尽管枚举有很多优点,但它仍然存在以下一些局限性−
- 类型安全问题 − 无作用域的枚举可能导致名称冲突,并允许隐式转换为整数,这会增加出错的风险。
- 功能受限 − 枚举具有一组固定的值,并且缺少无法在运行时扩展的成员函数。
- 调试困难 − 调试器可能会将枚举值显示为整数,这使得解释其含义变得更加困难。