Menu
CoddyTech

枚举类与强类型

本课属于 Coddy C++ 学习旅程的“面向对象编程”单元。第 80 课,共 104 课。

C++11 引入了枚举类(也称为作用域枚举),用于解决传统 C 风格枚举的不足。它们提供了更强的类型安全性,并能防止意外误用枚举值。

传统枚举存在一些问题:枚举值会泄漏到外围作用域,并且会隐式转换为整数,从而导致难以察觉的 bug:

// 传统的 enum:有问题
enum Color { Red, Green, Blue };
enum TrafficLight { Red, Yellow, Green };  // 错误!Red 和 Green 已经定义过了

int x = Red;  // 隐式转换为 int(0)
if (Red == 0) { }  // 可以编译:将 enum 与 int 比较

枚举类通过限定值的作用域并阻止隐式转换,解决了这些问题:

enum class Color { Red, Green, Blue };
enum class TrafficLight { Red, Yellow, Green };  // 可以,没有冲突

Color c = Color::Red;      // 必须使用作用域运算符
// int x = c;              // 错误!不能隐式转换
int x = static_cast<int>(c);  // 需要显式转换

// if (c == 0) { }         // 错误!不能与 int 比较
if (c == Color::Red) { }   // 可以,比较的是相同类型

你还可以指定底层类型来控制内存:

enum class Status : uint8_t {
    Inactive = 0,
    Active = 1,
    Pending = 2
};

枚举类与面向对象编程(OOP)设计结合得很好,能让代码更易读,并在编译时而不是运行时捕获类型错误。

challenge icon

挑战

简单

让我们构建一个任务优先级系统,使用枚举类表示不同的优先级和任务状态。这能展示枚举类如何提供类型安全,并防止传统枚举可能导致的错误。

你将把代码分到 3 个文件中:

  • TaskTypes.h:为任务系统定义枚举类。

    创建一个 Priority 枚举类,包含以下值:Low、Medium、High 和 Critical。指定 int 为底层类型,值分别为 1、2、3 和 4。

    创建一个 Status 枚举类,包含以下值:Pending、InProgress 和 Completed。

    提供两个辅助函数:

    • priorityToString(Priority p):将优先级转换为字符串("Low"、"Medium"、"High" 或 "Critical")
    • statusToString(Status s):将状态转换为字符串("Pending"、"InProgress" 或 "Completed")
  • Task.h:定义一个使用这些枚举类的 Task 类。

    你的 Task 应存储名称(字符串)、Priority 和 Status。构造函数应接收名称和优先级,状态默认设为 Status::Pending。

    实现以下方法:

    • setStatus(Status s):更新任务状态
    • getPriorityValue():使用 static_cast 返回优先级的底层整数值
    • display():按以下格式输出任务:[name] - Priority: [priority] (Value: [value]) - Status: [status]
  • main.cpp:读取 3 个输入:
    1. 任务名称(字符串)
    2. 优先级(整数,1=Low,2=Medium,3=High,4=Critical)
    3. 状态(整数,0=Pending,1=InProgress,2=Completed)

    使用给定的名称和优先级创建一个 Task(使用 static_cast 将整数转换为相应的 Priority 枚举值)。然后根据第三个输入设置任务状态。最后,调用 display() 显示任务详情。

例如,输入 Fix bug、3 和 1 时:

Fix bug - Priority: High (Value: 3) - Status: InProgress

输入 Write docs、1 和 2 时:

Write docs - Priority: Low (Value: 1) - Status: Completed

输入 Deploy app、4 和 0 时:

Deploy app - Priority: Critical (Value: 4) - Status: Pending

注意,枚举类会让优先级和状态值完全分开。你不能意外地将 Priority 与 Status 进行比较,也不能把其中一个赋给另一个。整数和枚举值之间的转换必须显式使用 static_cast,这能让代码的意图更加清楚,并防止细微错误。

亲手试试

#include <iostream>
#include <string>
#include "Task.h"

using namespace std;

int main() {
    // 读取输入
    string taskName;
    int priorityInt;
    int statusInt;
    
    getline(cin, taskName);
    cin >> priorityInt;
    cin >> statusInt;
    
    // TODO: 用给定的名称和优先级创建一个 Task
    // 使用 static_cast 将 priorityInt 转换为 Priority 枚举类型
    
    // TODO: 根据 statusInt 设置任务的状态
    // 使用 static_cast 将 statusInt 转换为 Status 枚举类型
    
    // TODO: 调用 display() 显示任务详情
    
    return 0;
}
quiz icon自我测试

这节课包含一个小测验。开始学习即可作答,并记录你的进度。

面向对象编程中的所有课

自己练习: C++ 在线编译器