ПрограммированиеSenior C++ Developer

Расскажите о механизме 'enum class' (scoped enums) в C++. Чем он отличается от обычных перечислений и зачем был введён? Какие ошибки типичны при переходе со старых enum на enum class?

Проходите собеседования с ИИ помощником Hintsage

Ответ

В C++11 был введён механизм 'scoped enums' — ключевое слово enum class.

Основные отличия от классических enum:

  • Содержимое enum class имеет собственную область видимости (scope), нет загрязнения глобального пространства имён.
  • Не происходит неявного преобразования перечислителей к int (требуется явное приведение).
  • Тип enum class по умолчанию: int, но можно задать другой (например, enum class MyE : uint8_t { ... };).

Зачем нужен: Для повышения безопасности типов, предотвращения конфликтов имён, ошибочных сравнений и явного управления хранением.

Пример:

enum Color { Red, Green }; Color c = Red; // Обычный enum, Red виден глобально enum class State { Off, On }; State s = State::On; // Нужно указывать State::On

Нельзя писать:

enum class State { Off, On }; int x = State::On; // Ошибка! Только с кастом int y = static_cast<int>(State::Off); // OK

Вопрос с подвохом

Почему нельзя сделать логическое сравнение между значениями разных enum class, даже если они совпадают по именам и подлежащему типу?

Ответ:

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

Примеры реальных ошибок из-за незнания тонкостей темы.


История

Переходя с enum на enum class в проекте управления станками, забыли добавить явное преобразование при выводе значений в лог. Логи начали показывать "чужеродные" значения (не распознавали State::On как число), что усложнило отладку.


История

В REST-сервисе после миграции обычного enum на enum class код сравнивал значения различных перечислений из разных enum class. Компилятор не допускал это, автоматические тесты перестали собираться.


История

В системе аудита разработчики путали старый и новый синтаксис — иногда нечаянно объявляли enum class, но использовали перечислители без квалификатора, в итоге компилировался не тот код или возникали ошибки линковки из-за совпадающих имён.