Computer >> Hướng Dẫn Máy Tính >  >> Lập Trình >> C++

Kiểu liệt kê (Enum) trong C++

Enum (Enumeration) là kiểu dữ liệu do người dùng định nghĩa, cho phép gán tên cho các giá trị nguyên tử (integer constants), giúp code dễ đọc, an toàn kiểu (type-safe) hơn so với #define hoặc const int.

Cú pháp cơ bản (C++98)

enum Gender {
    Male,
    Female
};

Gender gender = Male; // Giá trị mặc định: Male=0, Female=1

Enum class (C++11) - Khuyến khích dùng

enum class (scoped enum) cung cấp phạm vi (scope) và type safety mạnh hơn:

enum class Color : int { // Có thể chỉ định underlying type
    Red = 1,
    Green = 2,
    Blue = 4
};

Color c = Color::Red; // Phải dùng Color::Red, không phải Red đơn lẻ
// int x = c; // LỖI: Không chuyển ngầm sang int
int x = static_cast<int>(c); // Phải ép kiểu tường minh

Ví dụ hoàn chỉnh

#include <iostream>
using namespace std;

enum class Status {
    Pending = 1,
    Running = 2,
    Success = 3,
    Failed = 4
};

void print_status(Status s) {
    switch (s) {
        case Status::Pending:  cout << "Đang chờ"; break;
        case Status::Running:  cout << "Đang chạy"; break;
        case Status::Success:  cout << "Thành công"; break;
        case Status::Failed:   cout << "Thất bại"; break;
    }
    cout << " (mã: " << static_cast<int>(s) << ")\n";
}

int main() {
    Status s = Status::Running;
    print_status(s); // Đang chạy (mã: 2)
    
    // So sánh
    if (s == Status::Running) cout << "Đang xử lý...\n";
    
    // Duyệt enum (C++20: magic_enum hoặc tự viết)
    // C++17: không có built-in iteration
    return 0;
}

Đầu ra

Đang chạy (mã: 2)
Đang xử lý...

So sánh enum vs enum class

Đặc điểmenum (unscoped)enum class (scoped)
Phạm vi tênGlobal/enclosing scopeTrong enum (Color::Red)
Chuyển ngầm sang intCÓKHÔNG (cần static_cast)
Chỉ định underlying typeC++11: CÓCÓ
Forward declarationKhó khănDễ dàng (C++11)

Bitmask với enum class (C++11)

enum class Permission : uint8_t {
    Read   = 1 << 0, // 1
    Write  = 1 << 1, // 2
    Execute = 1 << 2 // 4
};

// Overload operator| để kết hợp quyền
Permission operator|(Permission a, Permission b) {
    return static_cast<Permission>(static_cast<uint8_t>(a) | static_cast<uint8_t>(b));
}

Permission p = Permission::Read | Permission::Write; // = 3

Khuyến nghị

Luôn dùng enum class trong C++11 trở đi để tránh xung đột tên, tăng type safety, và code rõ ràng hơn.