Хороший пример использования перечислений - PullRequest
8 голосов
/ 30 декабря 2010

Я выучил перечисления , когда я выучил C, и время от времени я постоянно вспоминаю об этом, и большую часть времени, перечитывая из какого-то источника, мне приходило в голову, что это связано с факт, что я никогда не использую это в своем программировании, мой интерес к программированию сосредоточен вокруг алгоритмического решения проблем, поэтому я не уверен, где я мог бы использовать перечисления.

Может кто-нибудь предложить какой-нибудь хороший пример, когда использование enums делает вещи намного проще?

Буду признателен за алгоритмические примеры, но приветствуются как алгоритмические, так и неалгоритмические примеры.

Ответы [ 10 ]

20 голосов
/ 30 декабря 2010

Представьте, что вы программируете поиск в глубину и хотите пометить свои ребра, будь то дерево, назад, вперед или крест. Вы можете создать перечисление EDGE_TYPE с четырьмя возможностями и использовать его для обозначения ваших ребер.

19 голосов
/ 30 декабря 2010

При описании / наблюдении какого-либо атрибута какой-либо системы вы можете обнаружить, что этот атрибут может иметь любое значение из набора limited . Назовите эти значения, присвойте каждому целочисленное значение (код), соберите их в перечислении, и вы определили тип этого атрибута. Все действия, связанные с этим атрибутом, теперь могут использовать этот тип.

Пример: для некоторой системы мы можем рассматривать ее состояние как один из ее атрибутов. Мы можем наблюдать это и сказать, что оно может быть в «неинициализированном» состоянии, в состоянии «инициализация», «активное» или «незанятое» состояние (не стесняйтесь добавлять больше состояний здесь ...). Если вы хотите выполнить какое-либо действие в этой системе, но которое зависит от текущего состояния, как вы передадите информацию о состоянии в это действие (функцию)? Вы можете передавать строки «неинициализированный», «инициализация» ... но более эффективный, простой и безопасный от ошибок будет, если вы передадите только одно целое число из набора:

enum State
{
   Uninitialized,
   Initialization,
   Active,
   Idle
};

Эта функция будет иметь State в качестве аргумента и может использовать переключатель при решении, что делать в зависимости от текущего состояния:

void foo(..., const State state,...)
{
   ...
   switch(state)
   {
      case Uninitialized:
          cout << "Uninitialized" << endl;
          break;
      case Initialization:
          ...
   }
   ...
}

Использование типа перечисления для описания ограниченного набора значений атрибута безопаснее, чем использование набора #defines и целочисленной переменной. Например. если у вас есть:

#define UNINITIALIZED  0
#define INITIALIZATION 1
#define ACTIVE         2
#define IDLE           3

и

int nState;

ничто не может помешать вам присвоить любое целочисленное значение nState:

nState = 4; // What state is 4?

Если вы используете перечисление:

State state;

Вы не можете присвоить ему произвольное целочисленное значение, но только перечислитель (хотя базовый тип для перечисления целочисленный! - см. this ):

state = Active;
8 голосов
/ 30 декабря 2010

Я использую их как параметры для функций, а не как логические значения для улучшения читабельности моего кода.

4 голосов
/ 01 января 2011

Из всего сказанного об использовании перечислений в качестве символической константы, я хотел бы подчеркнуть, что в C ++ использование enum в классе дает очень хороший, читаемый и удобный способ инкапсуляции и демонстрации возможностей класса, например

class BlockCipher {
public:
  enum PaddingOptions { NO_PADDING, DEFAULT_PADDING, ZERO_PADDING /*...*/ }
  void encrypt(const std::string& cleartext, std::string& ciphertext, 
               PaddingOptions pad=DEFAULT_PADDING);
};

int main()
{
  std::string clear("hello, world");
  std::string encrypted;
  BlockCipher  encryptor;

  encryptor.encrypt(clear, encrypted, BlockCipher::NO_PADDING);
}
4 голосов
/ 30 декабря 2010

Одно из перечислений - сделать код более понятным на сайте вызовов.Сравните:

//Usage: Kick(Dog);

enum PetType
{
   Cat,
   Dog
};

void Kick(PetType p)
{
   switch(p)
   {
      case Cat:
        //Kick Cat
        break;
      case Dog:
        //Kick Dog
        break;
      default:
        //Throw an exception.
        break;
    }
}

//Usage: Kick(false);

void Kick(bool isCat)
{
    if (isCat)
    {
        //Kick Cat
    }
    else
    {
        //Kick Dog
    }
}

Несмотря на то, что логическое значение будет работать так же хорошо, кому-то, кто не знаком с этой функцией, нужно будет работать намного больше, чтобы определить, что она делает в случае, если логическое значениеиспользуемый.Kick(Dog) намного яснее, чем Kick(false).

4 голосов
/ 30 декабря 2010

Взгляните на обоснование enum в Википедии.

Стоит также упомянуть: Перечисляемые типы - перечисления

2 голосов
/ 20 августа 2015

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

typedef enum
{
   First_value, 
   Uninitialized,
   Initialization,
   Active,
   Idle,
   Last_value
} my_type;

void function(my_type state)
{
   if ((state > First_value) && (state < Last_value))
   {
       //Do stuff...
   }
}
2 голосов
/ 30 декабря 2010

enum s может облегчить чтение кода и улучшить проверку типов во время компиляции.

Проблемы с перечислениями

  1. Они могут быть преобразованы в int или unsigned int и назначен в такие переменные, таким образом, создание дыры в проверке типа выгоды.
  2. Имя их символа не может быть напечатано непосредственно. Передав enum std::cout Результаты в enum конвертируется в целое число, а затем печатается из. Большинство реализаций должны выполнить поиск таблицы для преобразования enum к тексту перед печатью.

Альтернативы

Другой альтернативой enum является использование строки. Я работал в магазинах, где они передают постоянную строку вместо перечисления. Одним из преимуществ является то, что именованное значение всегда доступно, даже когда символы отладки не доступны. Также не требуется никаких преобразований при печати.

Некоторые недостатки строк:

  1. Не может использоваться в операторе switch.
  2. Чувствительность к регистру при сравнении.
  3. Сравнение может занять больше времени время.
  4. Занимает больше данных или исполняемого файла пространство.
1 голос
/ 30 декабря 2010

Перечисления имеют одно преимущество перед #define, но это просто деталь реализации: отладчики обычно могут показывать / использовать enum значения, но #define d значения.

С другой стороны, #define имеет несколько фундаментальных преимуществ, одним из которых является то, что вы можете проверить существование с помощью #ifdef. Это полезно, если вам нужно поддерживать несколько версий библиотеки и при желании использовать новые варианты, подобные перечислению, если они доступны.

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

#define FOO FOO
#define BAR BAR

и т.д.

0 голосов
/ 30 декабря 2010

Я запустил личный проект и хотел идентифицировать свой пакетный идентификатор, он выглядит следующим образом:

enum{
//Client to server
    //Connection
    ID_KEEP_ALIVE       = 0x00,
    ID_LOGIN_REQUEST    = 0x01,
    ID_CONNECTING       = 0x02,
    ID_DISCONNECT       = 0x03,

    //Player actions
    ID_PLAYER_INFO      = 0x04,
    ID_PLAYER_MOVE      = 0x05,
    ID_PLAYER_ATTACK    = 0x06,

    //Inventory
    ID_LOOT_ITEM        = 0x10,
    ID_DESTROY_ITEM     = 0x12,
    ID_USE_ITEM         = 0x13,
    ID_EQUIP_ITEM       = 0x15,
    ID_UNEQUIP_ITEM     = 0x16,
    ID_DROP_ITEM        = 0x17,
};

, а затем, когда я получаю пакет, у меня есть огромный переключатель, которыйвыглядит так, чтобы обрабатывать пакеты и отправлять их:

switch(packet.packetID){
    case ID_KEEP_ALIVE:
        //...
        break;
    case ID_LOGIN_REQUEST:
        //...
        break;
    case ID_CONNECTING:
        //...
        break;
    case ID_DISCONNECT:
        //...
        break;
    //..
}

это мой лучший пример, наслаждайтесь:)

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...