Fortement typé énumérations en C ++

La programmation est tout au sujet de la lisibilité. Il est difficile (en fait, il est impossible) pour écrire et maintenir un programme que vous ne pouvez pas lire. Une partie de la lecture d'un article du code source est de comprendre ce que les chiffres utilisés dans le programme représentent. L'aide la plus élémentaire que C ++ fournit est l'omniprésent #define, comme dans l'exemple souvent cité ci-dessous:

PI #define 3,141592653589793

Cette solution est acceptable pour les valeurs individuelles, mais il souffre du fait que la #define mécanisme est pas (à proprement parler) une partie de C / C ++ depuis le préprocesseur exécute avant le compilateur. En réponse à cela, C ++ 2,011 introduit une expression constante construire:

constexpr long double PI = 3.141592653589793-

La inconvénientstexpr mot-clé apporte des constantes dans la tente de la C. Ce PI a un type réel, comme les variables de l'autre C. C ++ peut générer des messages d'erreur avec PI qui font beaucoup plus de sens que celles impliquant 3,14159.

Les expressions constantes sont très bien pour des valeurs constantes individuelles, mais souvent constantes représentent des ensembles de choses plutôt que de constantes naturelles, comme dans l'exemple suivant:

#define DC_OR_TERRITORY 0 # définissent ALABAMA 1 # 2 # définissent ALASKA définissent ARKANSAS 3 // ... et ainsi de suite ...

On peut supposer que ces constantes sont utilisées pour identifier les états, peut-être utilisés comme un index dans un tableau d'objets de l'Etat ou comme une valeur dans une base de données quelque part.

C ++ a longtemps eu un mécanisme amélioré pour définir ces types de constantes - l'énumération:




énumération ÉTAT {DC_OR_TERRITORY, // obtient 0ALABAMA, // obtient 1ALASKA, // obtient 2ARKANSAS, // ... et ainsi de suite ...} -

La ENUM mot-clé introduit une séquence de constantes appelé un "recensement". Dans ce cas, l'énumération porte le nom ÉTAT. Chaque élément de cette énumération est attribué une valeur à partir de 0 et en augmentant séquentiellement par 1, donc DC_OR_TERRITORY est défini comme étant égal à 0, ALABAMA est défini comme étant 1, et ainsi de suite. Vous pouvez remplacer ce séquençage incrémentale en utilisant une instruction Affecter comme suit:

énumération ÉTAT {DC, TERRITOIRE = 0, Alabama, Alaska, // ... et ainsi de suite ...} -

Cette version de ÉTAT définit un élément DC, qui est donnée la valeur 0. Il définit ensuite un nouvel élément TERRITOIRE, qui est également affecté la valeur 0. ALABAMA ramasse avec 1, tout comme avant.

Dans la pratique, le programmeur peut utiliser les énumérations d'écrire du code tout à fait lisible comme ce qui suit:

à double TaxRate (état S) {return taxRatesByState [s] -}

Le seul problème avec cette approche est que cette énumération ne crée pas un nouveau type (comme vous pourriez le penser). En effet, selon la norme, ÉTAT est juste un autre nom pour int - et les constantes ALABAMA, ALASKA, et ainsi de suite sont tous de type const int.

Le compilateur gcc ne fournit en fait un ENUM déclaré de cette manière un peu plus d'autorité que de simplement appeler une autre forme de int. Vous pouvez effectivement surcharger fonctions basée sur une ENUM Type:

fn vides (STATE s) fn -void (int n) -fn (Alaska) - // invoque fn (ETAT)

Le Standard 2011 permet au programmeur de créer un tout nouveau type utilisant le ENUM mot-clé. Depuis les créateurs de la nouvelle norme ne veulent pas casser le code existant, la norme exige l'ajout d'un mot clé supplémentaire dans le but de définir un type d'énumération, comme dans l'exemple suivant:

classe d'énumération ÉTAT {DC, TERRITOIRE = 0, Alabama, Alaska, // ... et ainsi de suite ...} -

Une classe d'énumération est maintenant un type à grande échelle comme toute autre classe définie par l'utilisateur. Le texte suivant est même pas juridique plus pour deux raisons:

int s = Alaska-

Tout d'abord, la constante ALASKA est uniquement définie dans la ÉTAT namespace. Ainsi, le nom de la constante est ÉTAT :: ALASKA. En second lieu, le type est pas int mais ÉTAT. Vous ne pouvez pas affecter une valeur de type ÉTAT à un int.

= L'ETAT de l'Etat :: Alaska-

Le programmeur peut reformuler une ÉTAT dans une int mais elle doit le faire explicitement conversions -implicit ne coupent avec classes d'énumération:

int n = (int) ETAT :: Alaska-

Ce nouveau type d'énumération peut également être fondée sur l'un des autres types de numéros de comptage mais pas seulement int:

classe d'énumération ÉTAT: char {DC, // ... le reste de la déclaration est le même

» » » » Fortement typé énumérations en C ++