C++学习笔记——枚举类型
C++ 枚举类型学习笔记
今天学习了 C++ 中枚举(enum)的几种用法,感觉对枚举的作用域和类型安全有了更清晰的认识!
1. 传统枚举(enum)—— 优点和“坑”
优点:
- 定义一组命名的整数常量,让代码更易读。比如用
RED代替0,一眼就知道是什么意思。
“坑”:作用域污染!
- 问题:传统枚举的枚举项会“跑”到它所在的作用域里。比如我在全局定义一个
enum { RED, BLUE };,那RED和BLUE就像全局变量一样,可能会和别的变量或常量重名,导致冲突。 - 解决办法(不完美):
- 用
namespace包起来:这样1
2
3
4namespace Color {
enum Type { RED = 15, YELLOW, BLUE };
};
// 使用时:Color::Type c = Color::RED;RED就被限制在Color命名空间里了。但命名空间可以被后续扩充,在大项目里还是有重名的风险。 - 用
struct或class包起来:这种方法比1
2
3
4struct Color1 {
enum Type { RED = 102, YELLOW, BLUE };
};
// 使用时:Color1::Type c11 = Color1::BLUE;namespace更“封闭”,因为结构体/类的内容不会被随意扩充。
- 用
访问小细节(struct 包裹时):
- **
c1.REDvsColor1::Type::BLUE**:Color1 c1; cout << c1.RED << endl;:这种写法语法上允许,因为传统枚举项会被提升到父级结构体/类的作用域,可以像访问静态成员一样通过实例或类名访问。但不推荐!容易让人误解RED是c1实例的成员,语义不清晰。Color1::Type c11 = Color1::Type::BLUE;:这是标准且推荐的写法!它清晰地表明BLUE是Color1结构体中Type枚举类型的一个值,语义明确,符合最佳实践。
2. C++11 强类型枚举(enum class)—— 现代 C++ 的选择!
优点:
- 彻底解决作用域污染:枚举项只在
enum class自己的作用域内可见,比如Color2::RED。再也不用担心重名了! - 类型安全:这是最重要的!
enum class的枚举项不能隐式转换为整数类型。这意味着你不能不小心把一个枚举值当成整数用,避免了潜在的错误。 - 可以前向声明:这在某些场景下很有用,比如在头文件中只声明枚举类,在源文件中定义。
1
2
3enum class Color3 : char; // 必须指定底层类型
// ...
enum class Color3 : char { RED = 'r', BLUE };
使用和输出:
- 定义:
1
2enum class Color2 { RED = 2, YELLOW, BLUE }; // 默认底层类型是 int
enum class Color3 : char { RED = 'r', BLUE }; // 指定底层类型为 char - 访问:必须使用
枚举类名::枚举项,例如Color2::RED。 - 输出:
- **不能直接
cout << c2 << endl;**:这会编译报错!因为cout不知道怎么打印enum class类型。 - 需要显式转换:如果你想打印它的整数值,必须进行显式类型转换:
1
2Color2 c2 = Color2::RED;
cout << static_cast<int>(c2) << endl; // 输出 2 - 想输出名称字符串?:如果你想直接输出 “RED” 这样的字符串,你需要自己为
enum class**重载operator<<**。这需要一些额外的代码来把枚举值映射到字符串。
- **不能直接
总结:
enum class 是 C++11 带来的一个非常棒的改进,它让枚举变得更安全、更清晰。在新的 C++ 项目中,应该优先使用 enum class 来定义枚举类型。
希望这篇笔记能帮助我更好地理解和使用 C++ 枚举!
本博客所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议。转载请注明来自 iBlog!
