Урок 59. Классы enum

  Юрий Ворон  | 

    | 

  Обновл. 7 мая 2017  | 

 9897

 ǀ   5 

Хоть перечисления считаются отдельными типами данных в C++, они не столь безопасны, как кажутся на первый взгляд, и в некоторых случаях позволят вам делать вещи, которые не имеют смысла. Рассмотрим следующий пример:

Когда C++ будет сравнивать переменные fruit и color, он неявно преобразует fruit и color в целочисленные значения и сравнит их как целые числа. Так как значениями этих двух переменных являются перечислители, которым присвоено значение 0, то это означает, что в примере выше fruit будет равен color. А это не совсем то, что должно быть, так как fruit и color из разных перечислений и их вообще нельзя сравнивать (фрукт и цвет)! С обычными перечислителями нет способа предотвратить подобные сравнения.

Но в C++ 11 появляется новое понятие — класс enum (или перечисление с областью видимости), который добавляет перечислению, как вы уже могли понять, локальную область видимости с её правилами и строгие правила типов. Для создания такого класса нужно просто добавить ключевое слово class сразу после enum. Например:

Стандартные перечислители находятся в одной области с самим перечислением (глобальная область видимости), поэтому вы можете напрямую получать к ним доступ (например, PINK). Однако с добавлением класса, который ограничивает область видимости каждого перечислителя к его перечислению, для доступа потребуется использовать оператор разрешения области видимости (например, Colors::PINK). Это значительно снижает риск возникновения конфликтов имен.

Поскольку перечислители являются частью класса enum, то необходимость добавлять префиксы к идентификаторам отпадает (например, можно использовать просто PINK вместо COLOR_PINK, так как Colors::COLOR_PINK уже излишне).

А строгие правила типов означают, что каждый класс enum считается уникальным типом. Это означает, что компилятор не сможет неявно сравнивать перечислители с разных перечислений. Если вы попытаетесь это сделать, компилятор выдаст ошибку, как в примере выше.

Однако учтите, что вы можете сравнивать перечислители внутри одного класса enum (так как они одного типа):

С классами enum компилятор больше не сможет неявно конвертировать значения перечислителей в целые числа. В общем, это хорошо. Но иногда могут быть ситуации, когда нужно будет вернуть эту особенность. В таких случаях вы можете явно преобразовать перечислитель класса enum в int, используя static_cast:

Если вы используете компилятор C++ 11, то нет смысла использовать обычные перечисления вместо классов enum.

Обратите внимание, ключевое слово class вместе с ключевым словом static является одним из самых запутанных в языке C++, поскольку может иметь разные значения в зависимости от контекста. Хотя классы enum используют ключевое слово class, в C++ они не считаются традиционными «классами». О традиционных классах мы поговорим позже.

Оценить статью:

Звёзд: 1Звёзд: 2Звёзд: 3Звёзд: 4Звёзд: 5 (72 оценок, среднее: 4,89 из 5)
Загрузка...

Комментариев: 5

  1. Владимир:

    Возвращаясь к уроку 46, можно вместо такой записи

    Использовать такую:

    Как плюсы, используется 4 байта для всех флагов (сюда можно затолкать и 32 флага) вместо 8 байтов + повышение читабельности кода. Единственное, что нехорошо — постоянно придётся делать явное преобразование типов:

    Но если убрать ключевое слово class, то можно работать с флагами без преобразования.

    1. Константин:

      Владимир, а скажи мне: в чём разница между

      и

      ?

      Если это ОЧЕпятка, то как у тебя этот код вообще работал? Если это просто теория, то набросай какую задачу можно целиком (не фрагмент) этими флагами решить. Спасиб.

      1. Владимир:

        Как я указал в комменте, разница в том, что emun выделит 4 байта для хранения этих флагов, в то время как каждое использование const unsigned char будет создавать переменную размером в 1 байт. Если создать 32 флага, то через const unsigned char это всё займет 32 байта, в то время, как через enum — все те же 4. Так же повышает и читабельность кода, т.к. флаги группируются в одно перечисление, к тому же получают своё имя, по которому сгруппированы. Ещё раз повторюсь, читать коммент надо было внимательнее, я там всё это указал.
        Код прекрасно работает, если не знаком с битовыми масками, то тебе в 46-ой урок, читай, вникай. Там и задача как раз есть, её и реши, только вместо этого:

        Используй это:

  2. Алибек:

    Что-то я не вижу преимуществ enum перед enum class

    1. Юрий Юрий:

      Классы enum добавили позднее и это уже усовершенствованные enum. Если ваш компилятор поддерживает C++11, то смысла использовать enum в рабочих проектах, вместо классов enum — нет.

Добавить комментарий

Ваш E-mail не будет опубликован. Обязательные поля помечены *