1. 作用域
- 传统枚举:枚举成员位于其定义所在的作用域中,不同枚举类型的枚举成员如果名字相同会产生冲突。例如:
enum Color { Red, Green, Blue };
enum Fruit { Red, Orange, Banana }; // 此处Red会与Color中的Red冲突
- 强类型枚举(
enum class
):枚举成员被封装在枚举类型的作用域内,不同enum class
的枚举成员即使名字相同也不会冲突。例如:
enum class Color { Red, Green, Blue };
enum class Fruit { Red, Orange, Banana }; // 此处不会冲突
Color c = Color::Red;
Fruit f = Fruit::Red;
2. 类型安全
- 传统枚举:可以隐式转换为整数类型,也可以与整数类型进行比较等操作,缺乏类型安全性。例如:
enum Direction { Up, Down, Left, Right };
Direction d = Up;
if (d == 1) { // 这里将Direction隐式转换为整数进行比较,可能导致逻辑错误
// do something
}
- 强类型枚举(
enum class
):不会隐式转换为其他类型,必须显式转换,提高了类型安全性。例如:
enum class Direction { Up, Down, Left, Right };
Direction d = Direction::Up;
// if (d == 1) { // 编译错误,不能隐式转换
// // do something
// }
if (static_cast<int>(d) == 1) { // 显式转换后可以比较
// do something
}
3. 底层存储
- 传统枚举:底层存储类型默认为
int
,但也可以指定为char
、short
等整数类型。例如:
enum : char { SmallValue1, SmallValue2 }; // 底层存储类型为char
- 强类型枚举(
enum class
):默认情况下,底层存储类型也是int
,同样可以显式指定。例如:
enum class : char Status { Success, Failure }; // 底层存储类型为char
4. 实际应用场景
- 优先使用强类型枚举的场景:
- 状态机:在实现状态机时,强类型枚举可以确保状态的类型安全。例如:
enum class ConnectionState {
Disconnected,
Connecting,
Connected,
Disconnecting
};
ConnectionState state = ConnectionState::Disconnected;
// 状态转换操作,由于类型安全,减少错误
if (state == ConnectionState::Disconnected) {
state = ConnectionState::Connecting;
}
- **命令模式**:用于表示命令的枚举,强类型枚举能避免命名冲突。例如:
enum class Command {
Move,
Rotate,
Scale
};
void executeCommand(Command cmd) {
// 根据不同命令执行相应操作
}
- 传统枚举能满足需求的场景:
- 简单标志位:例如表示文件权限,只需要简单的整数映射。例如:
enum FilePermissions {
Read = 1 << 0,
Write = 1 << 1,
Execute = 1 << 2
};
FilePermissions perms = FilePermissions(Read | Write);
if (perms & Read) {
// 有读权限
}
- **与C语言代码交互**:当需要与C语言代码交互时,传统枚举由于其与C语言枚举的兼容性,可能更合适。例如:
// C语言风格的函数
void cFunction(int value);
enum OldStyleEnum { Value1, Value2 };
OldStyleEnum e = Value1;
cFunction(static_cast<int>(e)); // 与C语言函数交互,传统枚举更方便隐式转换