【C++11 之强类型枚举enum class/struct 基本结构及应用场景】了解在enum基础上增加了什么
C++11 中的强类型枚举(也称为枚举类)通过 enum class 或 enum struct 关键字来定义。它们的基本结构与传统枚举(通过 enum 定义)相似,但在类型安全性和作用域上有所不同。以下是强类型枚举的基本结构代码说明及解析:
基本结构
// 声明一个名为 Color 的强类型枚举,底层类型为 unsigned int
enum class Color : unsigned int { RED, // 枚举值,通常是大写的 GREEN, BLUE, // 可以有其他枚举值
}; // 使用枚举类
int main() { Color myColor = Color::RED; // 使用枚举类的作用域解析运算符 :: 来指定枚举值 // ... 其他代码 ... return 0;
}
解析
- 关键字:enum class 或 enum struct 用于声明强类型枚举。实际上,enum struct 和 enum class 在 C++ 中是等价的。
- 枚举名:在这个例子中,枚举名是 Color。你可以根据需要选择任何合法的标识符作为枚举名。
- 底层类型:: unsigned int 指定了枚举的底层类型为 unsigned int。如果不指定底层类型,则默认为 int。选择适当的底层类型可以优化内存使用和提高性能。
- 枚举值:枚举值(如 RED、GREEN、BLUE)是枚举类型的成员。它们通常是大写的,以增加代码的可读性。每个枚举值在底层类型上都有一个唯一的值。默认情况下,第一个枚举值从 0 开始,后续枚举值依次递增。但是,你也可以显式地为枚举值指定值。
- 作用域:强类型枚举的成员(即枚举值)具有枚举类型的作用域。这意味着你不能在枚举类型的作用域之外直接使用枚举值,除非使用枚举类型名和作用域解析运算符 :: 来指定它们。这有助于减少命名冲突和提高代码的可读性。
- 类型安全性:强类型枚举具有更高的类型安全性。它们不会隐式地转换为其他类型(如 int),这有助于防止意外的类型转换和类型错误。如果需要将强类型枚举值转换为其他类型,必须显式地使用类型转换运算符(如 static_cast)。
应用场景
- 避免隐式转换:当不希望枚举值被隐式转换为其他类型(如整型)时,强类型枚举是一个很好的选择。
- 减少命名冲突:在大型项目中,不同的枚举类型可能包含相同的枚举值。使用强类型枚举可以避免这种命名冲突。
- 提高代码可读性:通过为枚举值提供明确的类型,可以使代码更具可读性。
案例
- 假设我们有一个表示颜色的枚举类型:
enum class Color { RED, GREEN, BLUE };
- 使用强类型枚举时,你需要指定类型前缀来访问枚举值,如下所示:
Color color = Color::RED;
- 此外,由于强类型枚举不会隐式地转换为整型,因此以下代码将导致编译错误:
int num = Color::RED; // 编译错误
- 但你可以通过显式转换来实现这一点:
int num = static_cast<int>(Color::RED); // 正确
- 你还可以显式地为枚举值指定值:
enum class Color : unsigned int { RED = 1, GREEN = 2, BLUE = 4, // 注意:这些值通常是用于位运算的,所以它们通常是 2 的幂
};
在这个例子中,RED 的值为 1,GREEN 的值为 2,BLUE 的值为 4。这种设计通常用于位运算,允许你使用按位或(|)运算符组合多个颜色值。例如,Color(RED | BLUE) 将表示同时包含红色和蓝色的颜色。但是,请注意,这种用法需要谨慎处理,并确保底层类型具有足够的位来表示所有可能的组合。
- 此外,由于强类型枚举具有作用域,因此你可以定义具有相同枚举值的两个不同枚举类型而不会引起冲突:
enum class Direction { UP, DOWN }; enum class TrafficLight { RED, // 不会与Color::RED冲突 YELLOW, GREEN };
在这个例子中,Direction::UP、Color::RED和TrafficLight::RED是三个完全不同的枚举值,分别属于不同的枚举类型。