enum class的优点
C++11 推出的 强类型枚举(enum class)
的主要优势在于:
- 提供了更好的类型安全:不能直接看做整型数据,枚举就是枚举,不能做整型相关的运算
- 以及更严格的作用域控制:带作用域,其类名就是作用域
- 可以显示指定其底层存储类型,默认为int。(为其他的比如char的话 有什么作用和意义我不太清楚,也没见过)
示例:
#include <iostream>
enum class Color : int
{
Red,
Green,
Blue
};
enum class Car : int
{
Red,
Green,
Blue
};
int main() {
// 1、不会冲突,枚举值都有各自的作用域
Color color = Color::Red;
Color Car = Car::Red;
// 2、不能隐式转换成int
// int value = color;
if (color == Color::Red)
{
std::cout << "The color is red." << std::endl;
}
return 0;
}
enum 的缺点(传统C风格枚举)
-
缺乏类型安全性: 可以隐式转换为整数。不同枚举类型的值混淆。比如:
enum Color {red, green}; enum Car {BMW, Audi}; int main() { Color color = red; Car car = BMW; if (color == car) // 这个if 是能通过编译的,很离谱 ... }
-
全局作用域: 传统的C风格枚举的成员在全局作用域中定义,这可能导致潜在的命名冲突。
enum Color {Red, Green, Blue};// 第一个文件 enum Color {Black, White};// 第二个文件 int main() { enum Color color = Red; // 编译器不知道Red是哪个枚举的成员,因为有两个名为Color的枚举 printf("Color: %d\n", color); // 编译错误 ... }
给每个枚举添加命名空间可以解决,其实也不太麻烦。。
-
编译器可能会报警告 (但可以全局禁用它的警告)
-
没有底层类型: 传统的C风格枚举没有明确的底层类型,通常默认为int。这可能导致不同编译器和平台之间的兼容性问题,因为int的大小可能会有所不同
重要:使用enum
还是enum class
?
取决于具体需求!并不是 enum class
就一定好!
enum
的缺点恰恰就是它的优点
enum 优点
-
整型值: enum 可以完全等同于一个整型,因此可以像整数一样进行运算。这使得它非常适合需要进行位运算或其他整数运算的情况。
-
简洁: enum 的定义相对简单,不需要额外的运算符重载或其他复杂的结构。这使得代码编写和阅读都更为直观。
比如,你希望你的枚举值支持位运算,如果用enum class
,你需要重载你所需要的位运算操作符
#include <iostream>
enum class FileAccess
{
READ = 1 << 0, // 1
WRITE = 1 << 1, // 2
EXECUTE = 1 << 2 // 4 为了方便做位运算,每个枚举值对应一个比特位为1
};
// 定义按位或运算符的重载
FileAccess operator|(FileAccess lhs, FileAccess rhs)
{
using T = std::underlying_type_t<FileAccess>;
return static_cast<FileAccess>(static_cast<T>(lhs) | static_cast<T>(rhs));
}
// ...其他运算符重载,如:& ^ ~ |= &= ^=
// 属实非常麻烦,如果还有其他类似的enum class 还要每个都写一遍,==噩梦
int main()
{
FileAccess myPermissions = FileAccess::READ | FileAccess::WRITE;
if (myPermissions & FileAccess::WRITE)
{
// 有写权限
}
return 0;
}
而使用enum,就非常简洁方便。
#include <iostream>
enum FileAccess
{
READ = 1 << 0,
WRITE = 1 << 1,
EXECUTE = 1 << 2
};
int main()
{
FileAccess myPermissions = FileAccess::READ | FileAccess::WRITE;
if (myPermissions & FileAccess::WRITE) {
// ....
}
return 0;
}