C++枚举学习
·
C++ 枚举类型详解
C++中有两种主要的枚举类型:传统枚举(enum) 和 有作用域枚举(enum class)。
1. 传统枚举(Unscoped Enum)
基本语法
enum EnumName {
VALUE1,
VALUE2,
VALUE3
};
示例代码
#include <iostream>
using namespace std;
// 传统枚举
enum Color {
RED, // 0
GREEN, // 1
BLUE // 2
};
enum Weekday {
MONDAY = 1,
TUESDAY, // 2
WEDNESDAY, // 3
THURSDAY, // 4
FRIDAY = 10,
SATURDAY, // 11
SUNDAY // 12
};
int main() {
Color c1 = RED;
Color c2 = GREEN;
cout << "c1: " << c1 << endl; // 输出: 0
cout << "c2: " << c2 << endl; // 输出: 1
Weekday today = FRIDAY;
cout << "Today is: " << today << endl; // 输出: 10
// 可以隐式转换为整型
int colorValue = BLUE; // 2
cout << "Blue value: " << colorValue << endl;
return 0;
}
传统枚举的问题
enum Color { RED, GREEN, BLUE };
enum TrafficLight { RED, YELLOW, GREEN }; // 错误!命名冲突
int main() {
Color c = RED;
int x = c; // 隐式转换,可能不是期望的行为
return 0;
}
2. 有作用域枚举(Scoped Enum - enum class)
基本语法
enum class EnumName {
VALUE1,
VALUE2,
VALUE3
};
示例代码
#include <iostream>
using namespace std;
// 有作用域枚举
enum class Color {
RED,
GREEN,
BLUE
};
enum class TrafficLight {
RED,
YELLOW,
GREEN
};
enum class FileStatus : uint8_t {
OK = 0,
NOT_FOUND = 1,
PERMISSION_DENIED = 2
};
int main() {
Color c1 = Color::RED;
TrafficLight light = TrafficLight::RED; // 没有命名冲突!
// 不能隐式转换为整型
// int x = c1; // 错误!
int x = static_cast<int>(c1); // 需要显式转换
cout << "Color value: " << x << endl; // 输出: 0
// 比较操作
if (c1 == Color::RED) {
cout << "It's red!" << endl;
}
// 指定底层类型的枚举
FileStatus status = FileStatus::NOT_FOUND;
auto statusValue = static_cast<uint8_t>(status);
cout << "Status value: " << static_cast<int>(statusValue) << endl;
return 0;
}
3. 枚举的高级特性
指定底层类型
#include <iostream>
#include <cstdint>
using namespace std;
// 指定底层类型
enum class SmallEnum : char {
A = 'a',
B = 'b',
C = 'c'
};
enum class IntEnum : int {
VALUE1 = 100,
VALUE2 = 200,
VALUE3 = 300
};
int main() {
SmallEnum se = SmallEnum::A;
cout << "Size of SmallEnum: " << sizeof(se) << " bytes" << endl;
cout << "Value: " << static_cast<char>(se) << endl;
IntEnum ie = IntEnum::VALUE2;
cout << "Size of IntEnum: " << sizeof(ie) << " bytes" << endl;
cout << "Value: " << static_cast<int>(ie) << endl;
return 0;
}
枚举与switch语句
#include <iostream>
using namespace std;
enum class Operation {
ADD,
SUBTRACT,
MULTIPLY,
DIVIDE
};
double calculate(double a, double b, Operation op) {
switch (op) {
case Operation::ADD:
return a + b;
case Operation::SUBTRACT:
return a - b;
case Operation::MULTIPLY:
return a * b;
case Operation::DIVIDE:
if (b != 0) return a / b;
else throw runtime_error("Division by zero");
default:
throw runtime_error("Unknown operation");
}
}
int main() {
double result = calculate(10.5, 2.5, Operation::MULTIPLY);
cout << "Result: " << result << endl; // 输出: 26.25
return 0;
}
枚举作为函数参数和返回值
#include <iostream>
#include <string>
using namespace std;
enum class LogLevel {
DEBUG,
INFO,
WARNING,
ERROR
};
string logLevelToString(LogLevel level) {
switch (level) {
case LogLevel::DEBUG: return "DEBUG";
case LogLevel::INFO: return "INFO";
case LogLevel::WARNING: return "WARNING";
case LogLevel::ERROR: return "ERROR";
default: return "UNKNOWN";
}
}
class Logger {
public:
void setLevel(LogLevel level) {
currentLevel = level;
}
void log(LogLevel level, const string& message) {
if (level >= currentLevel) {
cout << "[" << logLevelToString(level) << "] " << message << endl;
}
}
private:
LogLevel currentLevel = LogLevel::INFO;
};
int main() {
Logger logger;
logger.setLevel(LogLevel::DEBUG);
logger.log(LogLevel::INFO, "Application started");
logger.log(LogLevel::DEBUG, "Debug information");
return 0;
}
4. 枚举的最佳实践
使用有作用域枚举(enum class)
// 推荐:使用enum class避免命名污染
enum class Direction {
NORTH,
SOUTH,
EAST,
WEST
};
// 不推荐:传统enum容易造成命名冲突
enum OldDirection {
NORTH, // 可能与其他枚举冲突
SOUTH,
EAST,
WEST
};
为枚举添加操作方法
#include <iostream>
#include <string>
using namespace std;
enum class Status {
PENDING,
PROCESSING,
COMPLETED,
FAILED
};
// 为枚举添加实用方法
namespace StatusUtils {
string toString(Status status) {
switch (status) {
case Status::PENDING: return "Pending";
case Status::PROCESSING: return "Processing";
case Status::COMPLETED: return "Completed";
case Status::FAILED: return "Failed";
default: return "Unknown";
}
}
bool isFinal(Status status) {
return status == Status::COMPLETED || status == Status::FAILED;
}
}
int main() {
Status taskStatus = Status::PROCESSING;
cout << "Status: " << StatusUtils::toString(taskStatus) << endl;
cout << "Is final: " << StatusUtils::isFinal(taskStatus) << endl;
return 0;
}
总结
| 特性 | 传统枚举 (enum) | 有作用域枚举 (enum class) |
|---|---|---|
| 作用域 | 无作用域,会污染外层 | 有作用域,需要Enum::Value |
| 隐式转换 | 允许隐式转换为int | 不允许,需要显式转换 |
| 类型安全 | 较低 | 较高 |
| 底层类型 | 默认int,可指定 | 默认int,可指定 |
| 推荐使用 | 旧代码兼容 | 新项目推荐 |
最佳实践建议:
- 在新代码中优先使用
enum class - 为枚举指定合适的底层类型以节省内存
- 为枚举提供相关的工具函数
- 避免使用魔术数字,使用有意义的枚举值
更多推荐


所有评论(0)