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

StackOverflow https://stackoverflow.com/questions/404231

  •  03-07-2019
  •  | 
  •  

Вопрос

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

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

Решение

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

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

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

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 теперь действителен Кнопка::Состояние ценить.Это не большая проблема, если вы передаете эти значения как целые числа.Но беда, если вы действительно ожидаете Кнопка::Состояние.

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

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

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

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

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

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

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

Другие советы

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

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

Затем вы можете определить массив, например

Color colors[STATE_COUNT];

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

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

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

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

enum ButtonState {
    BUTTON_NORMAL = 0,
    BUTTON_PRESSED,
    BUTTON_CLICKED,
    NUM_BUTTON_STATES
};

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

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

По стилю все в порядке.

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

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

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

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

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

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top