Перейти к содержанию

Последнее обновление:2026-10-12

Сильнотипизированные перечисления enum class в C++

В Effective modern C++ в пункте 10 «Prefer scoped enums to unscoped enum» подчёркивается, что вместо неограниченного (unscoped) enum следует использовать ограниченный (scoped) enum class.

Например:

enum Shape {circle,retangle};
auto circle = 10;  // error

Ошибка выше возникает потому, что оба circle находятся в одной и той же области видимости. Для enum это эквивалентно:

#define circle 0
#define retangle 1
Поэтому повторное определение circle далее вызовет ошибку.

Таким образом, неважно, совпадают ли имена самих перечислений — если их члены пересекаются, возникнет проблема. Например:

enum A {a,b};
enum B {c,a};
Имя a встречается дважды, и ошибка возникает в месте a внутри enum B.

Из сказанного выше мы знаем, что имя enum никак не ограничивает область видимости, поэтому нам на ум приходит namespace, как в следующем примере:

// 在创建枚举时,将它们放在名称空间中,以便可以使用有意义的名称访问它们:
namespace EntityType {
    enum Enum {
        Ground = 0,
        Human,
        Aerial,
        Total
    };
}

void foo(EntityType::Enum entityType)
{
    if (entityType == EntityType::Ground) {
        /*code*/
    }
}
Если давать пространствам имён осмысленные названия, можно добиться желаемого эффекта.

Однако постоянное использование пространств имён неизбежно слишком громоздко, а если не хочется использовать namespace, то достижение того же эффекта без него становится небезопасным и ничем не ограниченным.

Поэтому в C++11 был введён enum class.

enum class решает проблемы задания типа для членов перечисления, типобезопасности и ограничений. Вернёмся к рассмотренному выше примеру:

// enum class
enum class EntityType {
    Ground = 0,
    Human,
    Aerial,
    Total
};

void foo(EntityType entityType)
{
    if (entityType == EntityType::Ground) {
        /*code*/
    }
}
Это и есть та идиома, которой посвящён данный раздел: enum class.

Похожие темы

Комментарии