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
};

// Creating variable and assigning value
enumName enam_var = value;

这里,

  • **enumName** 是枚举的已声明变量名。
  • **variableName** 是枚举器(在枚举中定义的值)的变量名。

C++ 枚举示例

在下面的示例中,我们声明了一个枚举类型,声明了一个枚举的变量/对象,并访问了枚举常量。请考虑以下示例:

#include <iostream>
using namespace std;
// Define an enumeration called Day, for a days of week
enum Day {
   Sunday,      // 0
   Monday,      // 1
   Tuesday,     // 2
   Wednesday, // 3
   Thursday,     // 4
   Friday = 45,  // 45
   Saturday       // 46
};

int main() {
   // Declaring a variable for a day
   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;        // Here, no need to specify enum name
   int value = myColor;     // Implicit conversion to int

   cout << "Integer value: " << value << endl; // Outputs: 0
   printColor(myColor);      // Outputs: Color is Red

   return 0;
}

输出

Integer value: 0
Color is Red

2. 有作用域枚举 (enum class)

有作用域枚举是在 C++11 中引入的,使用 enum class 定义。它们提供了更好的类型安全性和组织性,其中它们的枚举器名称在枚举中具有作用域。这意味着将它们的标签保存在特定组中,因此在使用它们时需要提及组名。这有助于避免在不同组中具有类似标签时造成混淆。

枚举器名称在枚举类型中具有作用域,这意味着您必须使用枚举名称来访问它们。没有隐式转换为整数,这有助于增强类型安全性。

示例

#include <iostream>
using namespace std;

enum class Color {
   Red,    // Implicitly 0
   Green,  // Implicitly 1
   Blue    // Implicitly 2
};

// Usage
int main() {
   Color myColor = Color::Red;  // Must use enum name
   // int value = myColor;       // Error: no implicit conversion

   // Explicit conversion to int if needed
   int value = static_cast<int>(myColor);  // value = 0

   cout << "Integer value: " << value << endl; // Outputs: 0

   return 0;
}

输出

Integer value: 0

有作用域枚举与无作用域枚举

特性 无作用域枚举 有作用域枚举 (enum class)
枚举器作用域 全局作用域 枚举类型内的作用域
名称冲突 可能 避免
隐式转换
类型安全 较少 更多
底层类型 默认为 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
};

// Function that takes an enum as a parameter
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 语句配合使用,并允许使用分配的值对底层类型进行显式控制。

枚举的局限性

尽管有好处,但它仍然有一些如下所述的局限性:

  • **类型安全问题** - 无作用域枚举会导致名称冲突并允许隐式转换为整数,这会增加错误风险。
  • **功能有限** - 枚举具有一组固定的值,并且缺乏成员函数,无法在运行时扩展。
  • **调试困难** - 调试器可能会将枚举值显示为整数,这使得难以解释其含义。
广告