web-dev-qa-db-fra.com

Utilisation d'une énumération comme index de tableau

J'ai cette énumération:

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

const u8 NUM_BUTTON_STATES = 3;

Dans ma classe Button, j'ai des variables membres ButtonState state; et ButtonColors colors[NUM_BUTTON_STATES];. Lors du dessin du bouton, j'utilise colors[state] pour obtenir les couleurs de l'état du bouton.

Mes questions:

  1. Est-ce un bon style de programmation? Y a-t-il une meilleure façon de le faire? (Je n'utilise généralement que des énumérations avec des instructions switch ... l'utilisation d'une énumération comme index de tableau ne me semble pas correcte.)
  2. Dois-je avoir pour spécifier les valeurs de l'énumération? Il semble partir de 0 par défaut et incrémenter de 1 mais est-il garanti de fonctionner de cette façon dans tous les compilateurs?
56
Jeremy Ruten

Est-ce un bon style de programmation?

Je le pense. Je fais la même chose assez fréquemment.

Y a-t-il une meilleure façon de le faire?

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

L'inconvénient est que NUMBER_OF_BUTTON_STATES est maintenant une valeur valide Button :: State . Pas un gros problème si vous transmettez ces valeurs sous forme de entiers . Mais problème si vous attendez réellement un Button :: State .

Utiliser une énumération comme index de tableau ne semble pas correct.

C'est bien. Juste DOCUMENT ça, donc le prochain gars sait ce qui se passe! (C'est à cela que servent les commentaires.)

Dois-je spécifier les valeurs de l'énumération?

Sans affectation '=', les énumérations sont supposées commencer à zéro et augmenter progressivement.

Si une entrée d'énumération a une valeur affectée "=", les entrées d'énumération non "=" suivantes continuent de compter à partir de là.

Source: Le manuel de référence annoté C++ , p. 113

Cela dit, j'aime spécifier la valeur initiale juste pour rendre le code beaucoup plus clair.

47
Mr.Ree

Ouais ça marchera bien. Cela dit, dans tous les cas, vous vraiment devez mettre une autre entrée dans votre énumération définissant la valeur du nombre d'articles:

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

Ensuite, vous pouvez définir le tableau comme

Color colors[STATE_COUNT];

sinon, c'est un gâchis de garder la quantité d'états synchrones avec la taille du tableau. Les énumérations commenceront toujours par zéro si elles ne sont pas autrement initialisées, puis chaque entrée supplémentaire se verra attribuer une valeur supérieure à la précédente, si elle n'est pas autrement initialisée. Bien sûr, cela ne ferait pas de mal si vous mettez un zéro explicitement si vous le souhaitez. Si cela ne vous dérange pas de code supplémentaire, j'envelopperais l'accès au tableau brut à l'aide d'une fonction comme

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

Ou une fonction équivalente getColor transmettant la demande. Cela interdirait l'indexation directe du tableau avec un entier, ce qui échouerait presque certainement à un moment donné, car on se trompe d'index.

23

L'utilisation d'une énumération est correcte. Mais vous n'avez pas à spécifier de valeurs pour chaque élément. Il suffit de spécifier la première valeur. Je ne suppose pas que les énumérations commencent à 0, car j'ai utilisé des compilateurs qui ont utilisé 1 comme valeur de départ (pas pour les PC, mais certains compilateurs pour microcontrôleurs ont un comportement étrange). En outre, vous pouvez vous débarrasser de la const:

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

Question 1: Je pense que c'est un bon style de programmation. Je l'utilise tout le temps. Question 2: Pour autant que je sache, il est garanti de fonctionner de cette façon, vous n'avez donc pas à spécifier les valeurs.

Et je mettrais NUM_BUTTON_STATES dans l'énumération également.

3
Nathan Stoddard

Côté style, c'est très bien.

Les langages basés sur Pascal comme Delphi permettent de spécifier des limites de tableau en tant que type enum, vous ne pouvez donc utiliser que des éléments de ce type spécifique comme index.

3
Roddy

Il est parfaitement normal d'utiliser une énumération pour l'indexation dans un tableau.

Vous n'avez pas besoin de spécifier chaque valeur d'énumération, elles incrémenteront automatiquement de 1. Laisser le compilateur choisir les valeurs réduit la possibilité d'erreurs de frappe et de création d'un bogue, mais cela vous empêche de voir les valeurs, ce qui pourrait être utile pour le débogage.

1
Mark Ransom

C'est bien, mais je voudrais faire quelques vérifications des limites sur le tableau, comme si quelqu'un ajoute un autre ButtonState, vous aurez un problème.

De plus, les éléments du tableau de couleurs sont immuables, alors essayez peut-être d'utiliser une autre collection pour créer un tableau afin de pouvoir appliquer cette immuabilité. Peut-être un Dictionary<ButtonState,ButtonColor>

1
WOPR