0
0
CppComparisonBeginner · 4 min read

Enum vs enum class in C++: Key Differences and Usage

In C++, enum defines unscoped enumerations where enumerator names leak into the surrounding scope and implicit conversions to integers are allowed. enum class creates scoped enumerations that prevent name conflicts and disallow implicit conversions, providing better type safety.
⚖️

Quick Comparison

This table summarizes the main differences between enum and enum class in C++.

Featureenumenum class
Scope of enumeratorsGlobal within the enclosing scopeScoped inside the enum class
Implicit conversion to intAllowedNot allowed
Name conflictsPossible due to unscoped namesNo conflicts, names are scoped
Underlying typeUsually int, can be specifiedOptional to specify, defaults to int
Type safetyLow, can mix with integersHigh, strong typing enforced
Introduced inC++98C++11
⚖️

Key Differences

The traditional enum in C++ defines a set of named integer constants that are placed directly into the enclosing scope. This means you can use the enumerator names without qualifying them, but it also risks name clashes if different enums have the same enumerator names. Additionally, enum values implicitly convert to integers, which can lead to bugs if mixed unintentionally.

On the other hand, enum class (introduced in C++11) creates a scoped enumeration. The enumerator names are contained within the enum class scope, so you must qualify them with the enum class name. This prevents name conflicts. Also, enum class values do not implicitly convert to integers, improving type safety by forcing explicit casts when needed.

Furthermore, enum class allows specifying the underlying type explicitly, and if not specified, it defaults to int. This control over the underlying type can be useful for memory optimization or interfacing with other systems.

⚖️

Code Comparison

cpp
#include <iostream>

// Traditional enum
enum Color {
    Red,
    Green,
    Blue
};

int main() {
    Color c = Green; // No need to qualify
    int n = c;       // Implicit conversion allowed

    std::cout << "Color value: " << n << std::endl;

    // Name conflict example
    int Red = 10;    // Allowed, conflicts with enum Red
    std::cout << "Red variable: " << Red << std::endl;

    return 0;
}
Output
Color value: 1 Red variable: 10
↔️

enum class Equivalent

cpp
#include <iostream>

// Scoped enum class
enum class Color {
    Red,
    Green,
    Blue
};

int main() {
    Color c = Color::Green; // Must qualify enumerator
    // int n = c;           // Error: no implicit conversion
    int n = static_cast<int>(c); // Explicit cast needed

    std::cout << "Color value: " << n << std::endl;

    int Red = 10; // No conflict with Color::Red
    std::cout << "Red variable: " << Red << std::endl;

    return 0;
}
Output
Color value: 1 Red variable: 10
🎯

When to Use Which

Choose enum class when you want strong type safety, avoid name conflicts, and prefer scoped enumerators that require explicit qualification. It is the modern, safer choice for new C++ code.

Use traditional enum only when you need implicit conversions to integers or when working with legacy code that relies on unscoped enumerators. However, prefer enum class whenever possible to reduce bugs and improve code clarity.

Key Takeaways

enum class provides scoped enumerators and strong type safety.
Traditional enum allows implicit int conversion and unscoped names, risking conflicts.
Use enum class for modern, safer C++ code.
Explicit casts are required to convert enum class values to integers.
Choose enum only for legacy compatibility or when implicit conversion is needed.