枚举(Enumeration)是C++中一种用户定义的数据类型,用于定义一组命名的常量。枚举提供了一种将相关常量组织在一起的方式,使代码更加可读和易于维护。
传统枚举(C风格枚举)
基本语法和使用
#include <iostream>
#include <string>
// 基本枚举定义
enum Color {
RED, // 默认值为 0
GREEN, // 默认值为 1
BLUE, // 默认值为 2
YELLOW // 默认值为 3
};
// 指定枚举值
enum Status {
PENDING = 1,
PROCESSING = 5,
COMPLETED = 10,
FAILED = -1
};
// 枚举在函数中的使用
std::string getColorName(Color color) {
switch (color) {
case RED: return "红色";
case GREEN: return "绿色";
case BLUE: return "蓝色";
case YELLOW: return "黄色";
default: return "未知颜色";
}
}
void demonstrateBasicEnum() {
std::cout << "=== 基本枚举示例 ===" << std::endl;
// 声明和初始化
Color myColor = RED;
Status currentStatus = PROCESSING;
std::cout << "颜色值: " << myColor << " (" << getColorName(myColor) << ")" << std::endl;
std::cout << "状态值: " << currentStatus << std::endl;
// 枚举值的比较
if (myColor == RED) {
std::cout << "这是红色!" << std::endl;
}
// 遍历枚举值
std::cout << "所有颜色:" << std::endl;
for (int i = RED; i <= YELLOW; ++i) {
Color c = static_cast<Color>(i);
std::cout << " " << i << ": " << getColorName(c) << std::endl;
}
}
传统枚举的问题
#include <iostream>
// 问题1: 名称污染
enum Animal {
CAT,
DOG,
BIRD
};
enum Pet {
// CAT, // 错误!与上面的CAT冲突
HAMSTER,
FISH
};
// 问题2: 隐式转换为整数
void demonstrateProblems() {
std::cout << "\n=== 传统枚举的问题 ===" << std::endl;
Animal myAnimal = CAT;
// 问题:可以隐式转换为整数
int animalValue = myAnimal; // 这是允许的,但可能不是我们想要的
std::cout << "动物值: " << animalValue << std::endl;
// 问题:可以与整数进行比较
if (myAnimal == 0) { // 这样的比较是允许的,但语义不清
std::cout << "动物值等于0" << std::endl;
}
// 问题:可以进行算术运算
Animal nextAnimal = static_cast<Animal>(myAnimal + 1);
std::cout << "下一个动物值: " << nextAnimal << std::endl;
}
作用域枚举(C++11 强类型枚举)
基本语法
#include <iostream>
#include <string>
// 强类型枚举(enum class)
enum class Color {
Red,
Green,
Blue,
Yellow
};
enum class Status {
Pending = 1,
Processing = 5,
Completed = 10,
Failed = -1
};
// 指定底层类型
enum class Priority : char {
Low = 'L',
Medium = 'M',
High = 'H',
Critical = 'C'
};
// 枚举类的使用函数
std::string getColorName(Color color) {
switch (color) {
case Color::Red: return "红色";
case Color::Green: return "绿色";
case Color::Blue: return "蓝色";
case Color::Yellow: return "黄色";
}
return "未知颜色";
}
std::string getStatusName(Status status) {
switch (status) {
case Status::Pending: return "等待中";
case Status::Processing: return "处理中";
case Status::Completed: return "已完成";
case Status::Failed: return "失败";
}
return "未知状态";
}
void demonstrateScopedEnum() {
std::cout << "\n=== 强类型枚举示例 ===" << std::endl;
// 必须使用作用域限定符
Color myColor = Color::Red;
Status currentStatus = Status::Processing;
Priority taskPriority = Priority::High;
std::cout << "颜色: " << getColorName(myColor) << std::endl;
std::cout << "状态: " << getStatusName(currentStatus) << std::endl;
std::cout << "优先级: " << static_cast<char>(taskPriority) << std::endl;
// 强类型枚举不会隐式转换为整数
// int colorValue = myColor; // 错误!不能隐式转换
int colorValue = static_cast<int>(myColor); // 必须显式转换
std::cout << "颜色的整数值: " << colorValue << std::endl;
// 不同枚举类型之间不能直接比较
// if (myColor == currentStatus) {} // 错误!类型不匹配
// 同一枚举类型的比较
if (myColor == Color::Red) {
std::cout << "这是红色!" << std::endl;
}
}
枚举类的高级特性
#include <iostream>
#include <unordered_map>
#include <vector>
#include <type_traits>
// 带有方法的枚举类包装
class ColorUtils {
public:
enum class Color {
Red,
Green,
Blue,
Yellow,
Purple,
Orange
};
// 获取颜色名称
static std::string getName(Color color) {
static const std::unordered_map<Color, std::string> colorNames = {
{Color::Red, "红色"},
{Color::Green, "绿色"},
{Color::Blue, "蓝色"},
{Color::Yellow, "黄色"},
{Color::Purple, "紫色"},
{Color::Orange, "橙色"}
};
auto it = colorNames.find(color);
return (it != colorNames.end()) ? it->second : "未知颜色";
}
// 获取RGB值
static std::tuple<int, int, int> getRGB(Color color) {
switch (color) {
case Color::Red: return {255, 0, 0};
case Color::Green: return {0, 255, 0};
case Color::Blue: return {0, 0, 255};
case Color::Yellow: return {255, 255, 0};
case Color::Purple: return {128, 0, 128};
case Color::Orange: return {255, 165, 0};
}
return {0, 0, 0};
}
// 获取所有颜色
static std::vector<Color> getAllColors() {
return {
Color::Red, Color::Green, Color::Blue,
Color::Yellow, Color::Purple, Color::Orange
};
}
// 检查是否为暖色调
static bool isWarmColor(Color color) {
return color == Color::Red ||
color == Color::Yellow ||
color == Color::Orange;
}
// 混合两种颜色(简化版)
static Color mixColors(Color color1, Color color2) {
if ((color1 == Color::Red && color2 == Color::Blue) ||
(color1 == Color::Blue && color2 == Color::Red)) {
return Color::Purple;
}
if ((color1 == Color::Red && color2 == Color::Yellow) ||
(color1 == Color::Yellow && color2 == Color::Red)) {
return Color::Orange;
}
// 其他组合返回第一种颜色
return color1;
}
};
// 枚举迭代器
template<typename EnumType>
class EnumIterator {
private:
using UnderlyingType = std::underlying_type_t<EnumType>;
UnderlyingType current;
UnderlyingType end;
public:
EnumIterator(EnumType start, EnumType finish)
: current(static_cast<UnderlyingType>(start))
, end(static_cast<UnderlyingType>(finish)) {}
EnumType operator*() const {
return static_cast<EnumType>(current);
}
EnumIterator& operator++() {
++current;
return *this;
}
bool operator!=(const EnumIterator& other) const {
return current <= end;
}
EnumIterator begin() const {
return *this;
}
EnumIterator end() const {
EnumIterator endIter = *this;
endIter.current = end + 1;
return endIter;
}
};
void demonstrateAdvancedEnum() {
std::cout << "\n=== 高级枚举特性示例 ===" << std::endl;
using Color = ColorUtils::Color;
// 使用枚举工具类
Color myColor = Color::Red;
std::cout << "颜色: " << ColorUtils::getName(myColor) << std::endl;
auto [r, g, b] = ColorUtils::getRGB(myColor);
std::cout << "RGB值: (" << r << ", " << g << ", " << b << ")" << std::endl;
std::cout << "是暖色调吗: " << (ColorUtils::isWarmColor(myColor) ? "是" : "否") << std::endl;
// 颜色混合
Color mixedColor = ColorUtils::mixColors(Color::Red, Color::Blue);
std::cout << "红色 + 蓝色 = " << ColorUtils::getName(mixedColor) << std::endl;
// 遍历所有颜色
std::cout << "\n所有颜色及其RGB值:" << std::endl;
for (Color color : ColorUtils::getAllColors()) {
auto [r, g, b] = ColorUtils::getRGB(color);
std::cout << " " << ColorUtils::getName(color)
<< ": RGB(" << r << ", " << g << ", " << b << ")" << std::endl;
}
// 使用枚举迭代器
std::cout << "\n使用迭代器遍历颜色:" << std::endl;
EnumIterator<Color> colorRange(Color::Red, Color::Orange);
for (auto it = colorRange.begin(); it != colorRange.end(); ++it) {
std::cout << " " << ColorUtils::getName(*it) << std::endl;
}
}
枚举在实际项目中的应用
状态机实现
#include <iostream>
#include <string>
#include <functional>
#include <unordered_map>
// 游戏角色状态机
class GameCharacter {
public:
enum class State {
Idle,
Walking,
Running,
Jumping,
Attacking,
Defending,
Dead
};
enum class Event {
StartWalk,
StartRun,
Jump,
Attack,
Defend,
Stop,
TakeDamage,
Die
};
private:
State currentState;
std::string name;
int health;
// 状态转换表
std::unordered_map<State, std::unordered_map<Event, State>> transitions;
// 状态进入处理函数
std::unordered_map<State, std::function<void()>> stateHandlers;
public:
GameCharacter(const std::string& characterName)
: name(characterName), currentState(State::Idle), health(100) {
setupTransitions();
setupStateHandlers();
}
void setupTransitions() {
// 从Idle状态的转换
transitions[State::Idle][Event::StartWalk] = State::Walking;
transitions[State::Idle][Event::StartRun] = State::Running;
transitions[State::Idle][Event::Jump] = State::Jumping;
transitions[State::Idle][Event::Attack] = State::Attacking;
transitions[State::Idle][Event::Defend] = State::Defending;
// 从Walking状态的转换
transitions[State::Walking][Event::Stop] = State::Idle;
transitions[State::Walking][Event::StartRun] = State::Running;
transitions[State::Walking][Event::Jump] = State::Jumping;
transitions[State::Walking][Event::Attack] = State::Attacking;
// 从Running状态的转换
transitions[State::Running][Event::Stop] = State::Idle;
transitions[State::Running][Event::StartWalk] = State::Walking;
transitions[State::Running][Event::Jump] = State::Jumping;
transitions[State::Running][Event::Attack] = State::Attacking;
// 从Jumping状态的转换
transitions[State::Jumping][Event::Stop] = State::Idle;
// 从Attacking状态的转换
transitions[State::Attacking][Event::Stop] = State::Idle;
// 从Defending状态的转换
transitions[State::Defending][Event::Stop] = State::Idle;
// 死亡转换(从任何状态)
for (auto& stateMap : transitions) {
stateMap.second[Event::Die] = State::Dead;
}
}
void setupStateHandlers() {
stateHandlers[State::Idle] = [this]() {
std::cout << name << " 进入待机状态" << std::endl;
};
stateHandlers[State::Walking] = [this]() {
std::cout << name << " 开始行走" << std::endl;
};
stateHandlers[State::Running] = [this]() {
std::cout << name << " 开始奔跑" << std::endl;
};
stateHandlers[State::Jumping] = [this]() {
std::cout << name << " 跳跃中" << std::endl;
};