Mặc dù các kiểu enum là các loại khác nhau trong C ++, nhưng chúng không phải là loại an toàn và trong một số trường hợp sẽ cho phép bạn làm những việc mà không có ý nghĩa. Hãy xem xét trường hợp sau:

#include <iostream>
 
int main()
{
    enum Color
    {
        red, // red is placed in the same scope as Color
        blue
    };
 
    enum Fruit
    {
        banana, // banana is placed in the same scope as Fruit
        apple
    };
	
    Color color{ red }; // Color and red can be accessed in the same scope (no prefix needed)
    Fruit fruit{ banana }; // Fruit and banana can be accessed in the same scope (no prefix needed)
 
    if (color == fruit) // The compiler will compare a and b as integers
        std::cout << "color and fruit are equal\n"; // and find they are equal!
    else
        std::cout << "color and fruit are not equal\n";
 
    return 0;
}

Khi C ++ so sánh màu sắc và trái cây, thì nó sẽ hoàn toàn chuyển đổi màu sắc và trái cây thành số nguyên và so sánh các số nguyên. Vì màu sắc và trái cây đều được đặt thành các enum đánh giá với giá trị 0, điều này có nghĩa là trong ví dụ trên, màu sắc sẽ bằng trái cây. Điều này chắc chắn là không như mong muốn vì màu sắc và trái cây là từ các enum khác nhau và không có ý định so sánh! Với các phần tử chuẩn, không có cách nào để ngăn so sánh các phần tử từ các enum khác nhau.

C ++ 11 định nghĩa một khái niệm mới, class enum (còn được gọi là enum có phạm vi), làm cho các enum được nhấn mạnh và phạm vi mạnh hơn. Để tạo một lớp enum, chúng ta sử dụng lớp từ khóa sau từ khóa enum class. Dưới đây là một ví dụ:

#include <iostream>
 
int main()
{
    enum class Color // "enum class" defines this as a scoped enumeration instead of a standard enumeration
    {
        red, // red is inside the scope of Color
        blue
    };
 
    enum class Fruit
    {
        banana, // banana is inside the scope of Fruit
        apple
    };
 
    Color color{ Color::red }; // note: red is not directly accessible any more, we have to use Color::red
    Fruit fruit{ Fruit::banana }; // note: banana is not directly accessible any more, we have to use Fruit::banana
	
    if (color == fruit) // compile error here, as the compiler doesn't know how to compare different types Color and Fruit
        std::cout << "color and fruit are equal\n";
    else
        std::cout << "color and fruit are not equal\n";
 
    return 0;
}

Với các enum thông thường, các phần tử được đặt trong cùng phạm vi với chính của enum, do đó bạn có thể truy cập trực tiếp vào các phần tử đó (ví dụ: red). Tuy nhiên, với các lớp enum, các quy tắc phạm vi mạnh hơn có nghĩa là tất cả các phần tử được coi là một phần của enum, do đó bạn phải sử dụng một vòng loại phạm vi để truy cập phần tử đó (ví dụ: Color :: red). Điều này làm giảm rối tên và khả năng xung đột tên.

Bởi vì các phần tử là một phần của lớp enum, nên bạn không cần phải thêm tiền tố vào tên của điều tra viên (ví dụ: nó có thể sử dụng màu đỏ thay vì COLOR_red, vì Color :: COLOR_red là dư).

Các quy tắc nhấn mạnh có nghĩa là mỗi lớp enum được coi là một loại duy nhất. Điều này có nghĩa là trình biên dịch sẽ không ngầm so sánh các phần tử của enum khác nhau. Nếu bạn cố gắng làm như vậy, trình biên dịch sẽ đưa ra một lỗi, như trong ví dụ trên.

Tuy nhiên, lưu ý rằng bạn vẫn có thể so sánh các điều tra viên trong cùng một lớp enum (vì chúng cùng loại):

#include <iostream>
 
int main()
{
    enum class Color
    {
        red,
        blue
    };
 
    Color color{ Color::red };
 
    if (color == Color::red) // this is okay
        std::cout << "The color is red!\n";
    else if (color == Color::blue)
        std::cout << "The color is blue!\n";
 
    return 0;
}

Với các class enum, trình biên dịch sẽ không còn chuyển đổi các giá trị enum thành số nguyên. Đây chủ yếu là một điều tốt. Tuy nhiên, đôi khi có những trường hợp hữu ích để có thể làm như vậy. Trong những trường hợp này, bạn có thể chuyển đổi rõ ràng một lớp enum thành một số nguyên bằng cách sử dụng static_cast thành int:

#include <iostream>
 
int main()
{
    enum class Color
    {
        red,
        blue
    };
 
    Color color{ Color::blue };
 
    std::cout << color; // won't work, because there's no implicit conversion to int
    std::cout << static_cast<int>(color); // will print 1
 
    return 0;
}

Có rất ít lý do để sử dụng các kiểu enum bình thường thay vì các lớp enum.

Lưu ý rằng từ khóa class, cùng với từ khóa static, là một trong những từ khóa sử dụng nhiều nhất trong ngôn ngữ C ++ và có thể có các ý nghĩa khác nhau tùy thuộc vào ngữ cảnh. Mặc dù các class enum sử dụng từ khóa class, nhưng chúng được coi là các class theo nghĩa C ++ truyền thống. Chúng ta sẽ tìm hiểu các class thực tế sau này.

Ngoài ra, chỉ trong trường hợp bạn từng gặp phải nó, thì enum struct tương đương với enum class. Nhưng việc sử dụng này không được khuyến khích và không được sử dụng phổ biến.

Đăng ký kênh youtube để ủng hộ Cafedev nha các bạn, Thanks you!