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.RED
vsColor1::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!