018 C++的枚举类型(enum和enum class)
作者Lou Xiao, deepseek创建时间2025-04-02 15:04:00更新时间2025-04-02 15:04:00
1. 传统枚举(enum)
1.1 基本概念
- 传统枚举是C++从C语言继承的特性
- 定义方式:
enum 枚举名 {枚举值列表};
- 枚举值默认从0开始,依次递增
1.2 基本语法
1.双击鼠标左键复制此行;2.单击复制所有代码。
1
enum Color {
2
RED, // 0
3
GREEN, // 1
4
BLUE // 2
5
};
6
7
Color c = RED;
1.3 特性
- 隐式转换:枚举值可隐式转换为整数
- 作用域污染:枚举值暴露在包含枚举定义的作用域中
- 类型不安全:不同枚举类型之间可以比较
- 可指定值:可以显式为枚举值指定整数值
1.双击鼠标左键复制此行;2.单击复制所有代码。
1
enum HttpCode {
2
OK = 200,
3
NOT_FOUND = 404,
4
SERVER_ERROR = 500
5
};
1.4 局限性
- 不同枚举类型之间可以比较(类型不安全)
- 枚举值会污染所在作用域
- 无法指定底层类型(C++11前)
2. 枚举类(enum class)
2.1 基本概念
- C++11引入的新特性
- 定义方式:
enum class 枚举名 {枚举值列表};
- 强类型枚举,解决传统枚举的问题
2.2 基本语法
1.双击鼠标左键复制此行;2.单击复制所有代码。
1
enum class Color {
2
RED,
3
GREEN,
4
BLUE
5
};
6
7
Color c = Color::RED;
2.3 特性
- 强类型:不会隐式转换为整数
- 作用域限定:枚举值必须通过枚举名访问
- 类型安全:不同枚举类型不能比较
- 可指定底层类型:可以显式指定底层存储类型
1.双击鼠标左键复制此行;2.单击复制所有代码。
1
enum class Color : uint8_t {
2
RED = 1,
3
GREEN = 2,
4
BLUE = 3
5
};
2.4 优势
- 避免命名冲突
- 提高类型安全性
- 可控制底层类型
- 更符合现代C++的设计理念
3. 对比总结
特性 | enum | enum class |
---|---|---|
作用域 | 污染外层作用域 | 限定在枚举内部 |
隐式转换 | 允许 | 不允许 |
类型安全 | 弱 | 强 |
底层类型指定 | C++11后支持 | 支持 |
访问方式 | 直接访问 | 必须加枚举名限定 |
前向声明 | 需要完整定义 | 可直接声明 |
4. 使用建议
- 优先使用enum class:除非需要与旧代码兼容,否则应优先使用enum class
- 指定底层类型:当需要控制枚举的大小时,显式指定底层类型
- 避免隐式转换:即使使用传统enum,也应避免依赖隐式转换
- 考虑可读性:为枚举值使用有意义的名称
5. 高级用法
5.1 位标志枚举
1.双击鼠标左键复制此行;2.单击复制所有代码。
1
enum class FilePermissions : uint8_t {
2
READ = 1,
3
WRITE = 2,
4
EXECUTE = 4
5
};
6
7
FilePermissions perms = FilePermissions::READ | FilePermissions::WRITE;
5.2 枚举与switch语句
1.双击鼠标左键复制此行;2.单击复制所有代码。
1
enum class Status {
2
SUCCESS,
3
FAILURE,
4
PENDING
5
};
6
7
void handleStatus(Status s) {
8
switch(s) {
9
case Status::SUCCESS: /*...*/ break;
10
case Status::FAILURE: /*...*/ break;
11
case Status::PENDING: /*...*/ break;
12
}
13
}
5.3 枚举与运算符重载
1.双击鼠标左键复制此行;2.单击复制所有代码。
1
enum class Day {
2
MONDAY, TUESDAY, WEDNESDAY, THURSDAY, FRIDAY, SATURDAY, SUNDAY
3
};
4
5
Day& operator++(Day& d) {
6
d = static_cast<Day>((static_cast<int>(d) + 1) % 7);
7
return d;
8
}
6. 最佳实践
- 命名规范:使用大写字母和下划线命名枚举值(如
Color::RED
) - 相关操作封装:将与枚举相关的操作封装为函数
- 避免魔数:使用枚举代替硬编码的数字
- 文档注释:为枚举添加注释说明其用途和各个值的含义
7. 常见问题与解决方案
7.1 如何遍历枚举值?
1.双击鼠标左键复制此行;2.单击复制所有代码。
1
enum class Color { RED, GREEN, BLUE, COUNT };
2
3
for (int i = 0; i < static_cast<int>(Color::COUNT); ++i) {
4
Color c = static_cast<Color>(i);
5
// 使用c
6
}
7.2 如何将enum转换为字符串?
1.双击鼠标左键复制此行;2.单击复制所有代码。
1
const char* ColorToString(Color c) {
2
switch(c) {
3
case Color::RED: return "RED";
4
case Color::GREEN: return "GREEN";
5
case Color::BLUE: return "BLUE";
6
default: return "UNKNOWN";
7
}
8
}
7.3 如何将字符串转换为enum?
1.双击鼠标左键复制此行;2.单击复制所有代码。
1
Color StringToColor(const std::string& s) {
2
if (s == "RED") return Color::RED;
3
if (s == "GREEN") return Color::GREEN;
4
if (s == "BLUE") return Color::BLUE;
5
throw std::invalid_argument("Invalid color string");
6
}
8. C++20增强
C++20为枚举添加了更多特性:
- 使用using enum
引入枚举值到当前作用域
- 简化枚举值的访问
1.双击鼠标左键复制此行;2.单击复制所有代码。
1
enum class Color { RED, GREEN, BLUE };
2
3
void foo() {
4
using enum Color; // C++20特性
5
Color c = RED; // 无需Color::前缀
6
}
文章目录