Использование перечисления в качестве индекса массива - PullRequest
56 голосов
/ 01 января 2009

У меня есть это перечисление:

enum ButtonState {
    BUTTON_NORMAL = 0,
    BUTTON_PRESSED = 1,
    BUTTON_CLICKED = 2
};

const u8 NUM_BUTTON_STATES = 3;

В моем классе Button у меня есть переменные-члены ButtonState state; и ButtonColors colors[NUM_BUTTON_STATES];. При рисовании кнопки я использую colors[state], чтобы получить цвета для любого состояния, в котором находится кнопка.

Мои вопросы:

  1. Это хороший стиль программирования? Есть ли лучший способ сделать это? (Я обычно использую перечисления только с операторами switch ... использование перечисления в качестве индекса массива не подходит.)
  2. Есть ли у значение для указания значений перечисления? Кажется, он начинается с 0 по умолчанию и увеличивается на 1, но гарантированно ли это будет работать во всех компиляторах?

Ответы [ 7 ]

47 голосов
/ 01 января 2009

Это хороший стиль программирования?

Я так думаю. Я делаю то же самое довольно часто.

Есть ли лучший способ сделать это?

class Button
{
public:
    // Used for array indexes!  Don't change the numbers!
  enum State {
    NORMAL = 0,
    PRESSED,
    CLICKED,
    NUMBER_OF_BUTTON_STATES
  };
};

Недостатком является то, что NUMBER_OF_BUTTON_STATES теперь является действительным значением Button :: State . Не большая проблема, если вы передаете эти значения как int . Но проблема, если вы действительно ожидаете Button :: State .

Использование перечисления в качестве индекса массива не подходит.

Всё хорошо. Просто ДОКУМЕНТ это, так что следующий парень знает, что происходит! (Вот для чего и комментарии.)

Нужно ли указывать значения перечисления?

Без присвоения '=' предполагается, что в enum должны начинаться с нуля и увеличиваться вверх.

Если запись enum имеет присвоенное значение '=', последующие записи enum, отличные от '=', продолжат отсчитывать оттуда.

Источник: Справочное руководство по аннотированному C ++ , стр. 113

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

23 голосов
/ 01 января 2009

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

enum ButtonState {
    BUTTON_NORMAL,
    BUTTON_PRESSED,
    BUTTON_CLICKED,
    STATE_COUNT
};

Тогда вы можете определить массив как

Color colors[STATE_COUNT];

в противном случае бесполезно поддерживать количество состояний синхронным с размером массива. Перечисления всегда начинаются с нуля, если не инициализировано иначе, а затем каждой дополнительной записи будет присвоено значение на единицу выше предыдущей, если не инициализировано иначе Конечно, это также не повредит, если вы установите ноль явно, если хотите. Если вы не возражаете против дополнительного кода, я бы обернул доступ к массиву raw с помощью функции, подобной

Color & operator[](ButtonState state) {
    return array[state];
}

Или эквивалентная getColor функция переадресации запроса. Это запретило бы прямую индексацию массива с некоторым целым числом, которое почти наверняка в какой-то момент завершится сбоем, потому что каждый получает индексы неправильно.

15 голосов
/ 01 января 2009

Использование перечисления в порядке. Но вам не нужно указывать значения для каждого элемента. Достаточно указать первое значение. Я бы не предположил, что перечисления начинаются с 0, потому что я использовал компиляторы, которые использовали 1 в качестве начального значения (не для ПК, но некоторые компиляторы для микроконтроллеров ведут себя странно) Также вы можете избавиться от const:

enum ButtonState {
    BUTTON_NORMAL = 0,
    BUTTON_PRESSED,
    BUTTON_CLICKED,
    NUM_BUTTON_STATES
};
3 голосов
/ 01 января 2009

По стилю, это нормально.

Языки на основе Pascal, такие как Delphi, позволяют указывать границы массивов в качестве типа enum, поэтому в качестве индекса можно использовать только элементы этого определенного типа.

3 голосов
/ 01 января 2009

Вопрос 1: Я думаю, что это хороший стиль программирования. Я пользуюсь этим все время. Вопрос 2: Насколько я знаю, он гарантированно работает таким образом, поэтому вам не нужно указывать значения.

И я бы также поместил NUM_BUTTON_STATES в перечисление.

1 голос
/ 01 января 2009

Это нормально, но я бы хотел провести некоторую проверку границ массива, как будто кто-то добавляет еще одно ButtonState, у вас возникнет проблема.

Кроме того, элементы массива цветов являются неизменяемыми, поэтому, возможно, стоит рассмотреть возможность использования другой коллекции в массиве, чтобы можно было применять эту неизменность. Может быть Dictionary<ButtonState,ButtonColor>

1 голос
/ 01 января 2009

Совершенно нормально использовать перечисление для индексации в массиве.

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

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