Supposons que nous ayons un enum
comme ceci:
enum Days {Saturday, Sunday, Tuesday, Wednesday, Thursday, Friday};
Je veux créer une instance de ceci enum
et l'initialiser avec une valeur appropriée, alors je fais:
Days day = Days.Saturday;
Maintenant, je veux vérifier ma variable ou mon instance avec une enum
valeur existante , alors je fais:
if (day == Days.Saturday)
{
std::cout << "Ok its Saturday";
}
Ce qui me donne une erreur de compilation:
erreur: expression primaire attendue avant '.' jeton
Donc, pour être clair, quelle est la différence entre dire:
if (day == Days.Saturday) // Causes compilation error
et
if (day == Saturday)
?
À quoi ces deux se réfèrent-ils réellement, dans le sens où l'un est OK et l'autre provoque une erreur de compilation?
Réponses:
Ce code est faux:
Parce que ce
Days
n'est pas une portée, ni un objet. C'est un type. Et les types eux-mêmes n'ont pas de membres. Ce que vous avez écrit est l'équivalent destd::string.clear
.std::string
est un type, vous ne pouvez donc pas l'utiliser.
. Vous utilisez.
sur une instance d'une classe.Malheureusement, les énumérations sont magiques et donc l'analogie s'arrête là. Parce qu'avec une classe, vous pouvez faire
std::string::clear
pour obtenir un pointeur sur la fonction membre, mais en C ++ 03,Days::Sunday
n'est pas valide. (Ce qui est triste). C'est parce que C ++ est (quelque peu) rétrocompatible avec C, et C n'avait pas d'espaces de noms, donc les énumérations devaient être dans l'espace de noms global. La syntaxe est donc simplement:Heureusement, Mike Seymour observe que cela a été résolu en C ++ 11. Changez
enum
pourenum class
et il obtient sa propre portée;Days::Sunday
n'est donc pas seulement valable, mais c'est le seul moyen d'y accéderSunday
. Jours heureux!la source
enum
pourenum class
et il obtient sa propre portée;Days::Sunday
n'est donc pas seulement valable, mais c'est le seul moyen d'y accéderSunday
. Jours heureux!'.' token
etdot operator
, à part que c'est un jeton et non un opérateur, et il montre le symbole exact, plutôt qu'un nom.enum
, vous ne pouvez utiliser aucune étendue, ou l'étendue globale (::Saturday
). Si vous en avez unenum class
(ce qui est très différent), vous devez l' utiliserDays::Saturday
.Ce sera suffisant pour déclarer votre variable enum et la comparer:
la source
Days
n'est pas une portée, ni un objet. C'est un type. Et les types eux - mêmes n'ont pas de membres.std::string.clear
échoue également à compiler pour la même raison.enum class
, nouvelles en 2011) ont leur propre champ, et sont accessibles en utilisant l'opérateur de portéeDays::Saturday
. L'opérateur d'accès aux membres (.
) est uniquement utilisé pour accéder aux membres de la classe.Une grande partie de cela devrait vous donner des erreurs de compilation.
Maintenant,
Saturday
,Sunday
, etc. peuvent être utilisés comme des constantes nues de haut niveau, etDays
peut être utilisé comme un type:Et de même plus tard, pour tester:
Ces
enum
valeurs sont comme des constantes nues - elles n'ont pas de portée - avec un peu d'aide supplémentaire du compilateur: (à moins que vous n'utilisiez des classes d'énumération C ++ 11 ), elles ne sont pas encapsulées comme des membres d'objet ou de structure par exemple, et vous ne pouvez pas vous y référer en tant que membres deDays
.Vous aurez ce que vous cherchez avec C ++ 11 , qui introduit un
enum class
:Notez que ce C ++ est un peu différent de C de deux manières, l'une est que C nécessite l'utilisation du
enum
mot - clé lors de la déclaration d'une variable:la source
Vous pouvez utiliser une astuce pour utiliser les étendues comme vous le souhaitez, déclarez simplement enum de la manière suivante:
la source
Plutôt que d'utiliser un tas d'instructions if, les énumérations se prêtent bien aux instructions switch
J'utilise des combinaisons enum / switch dans le générateur de niveau que je construis pour mon jeu.
EDIT: Une autre chose, je vois que vous voulez une syntaxe similaire à;
Vous pouvez le faire en C ++:
Voici un exemple très simple:
EnumAppState.h
Somefile.cpp
la source
Si vous utilisez toujours C ++ 03 et souhaitez utiliser des énumérations, vous devez utiliser des énumérations dans un espace de noms. Par exemple:
Vous pouvez utiliser l'énumération en dehors de l'espace de noms comme,
la source
Vous recherchez des énumérations fortement typées , une fonctionnalité disponible dans la norme C ++ 11 . Il transforme les énumérations en classes avec des valeurs de portée.
En utilisant votre propre exemple de code, c'est:
L'utilisation en
::
tant qu'accesseurs aux énumérations échouera si vous ciblez une norme C ++ antérieure à C ++ 11. Mais certains anciens compilateurs ne le prennent pas en charge, ainsi certains IDE remplacent simplement cette option et définissent un ancien std C ++.Si vous utilisez GCC, activez C + 11 avec -std = c ++ 11 ou -std = gnu11 .
Soyez heureux!
la source
enum class Days { ...
.Cela ne devrait pas fonctionner en C ++:
Jours n'est pas une étendue ou un objet contenant des membres auxquels vous pouvez accéder avec l'opérateur point. Cette syntaxe n'est qu'un cismisme et n'est pas légale en C ++.
Microsoft a longtemps maintenu une extension C ++ qui vous permet d'accéder aux identifiants à l'aide de l'opérateur d'étendue:
Mais ce n'est pas standard avant C ++ 11. En C ++ 03, les identifiants déclarés dans une énumération n'existent que dans la même portée que le type énumération lui-même.
C ++ 11 rend légal la qualification des identificateurs d'énumération avec le nom d'énumération et introduit également des classes d'énumération, qui créent une nouvelle étendue pour les identificateurs au lieu de les placer dans l'étendue environnante.
la source
Malheureusement, les éléments de l'énumération sont «mondiaux». Vous y accédez en faisant
day = Saturday
. Cela signifie que vous ne pouvez pas avoirenum A { a, b } ;
etenum B { b, a } ;
car ils sont en conflit.la source
enum class
en C ++ 11, c'est. Avant cela, vous devez faire des cours factices.Alors que C ++ (à l'exception de C ++ 11) a des énumérations, les valeurs qu'elles contiennent sont "divulguées" dans l'espace de noms global.
Si vous ne voulez pas les faire fuir (et que vous N'AVEZ PAS BESOIN d'utiliser le type enum), tenez compte des points suivants:
la source
Les énumérations en C ++ sont comme des entiers masqués par les noms que vous leur donnez, lorsque vous déclarez vos valeurs d'énumération (ce n'est pas une définition seulement un indice sur la façon dont cela fonctionne).
Mais il y a deux erreurs dans votre code:
enum
tous les minusculesDays.
avant samedi.if (day == YourClass::Saturday){}
la source
Je pense que votre problème racine est l'utilisation de
.
au lieu de::
, qui utilisera l'espace de noms.Essayer:
la source
Days::
étendue comme dans votre exemple, vous devez définir l'énumération avecenum class Days
et utiliser l'extension Microsoft C ++ 03 + ou C ++ 11.-std=c++98
ou-std=c++03
. Clang est tout à fait clair:warning: use of enumeration in a nested name specifier is a C++11 extension
.Si nous voulons la sécurité de type stricte et l'énumération de portée, l'utilisation
enum class
est bonne en C ++ 11.Si nous devions travailler en C ++ 98, nous pouvons utiliser les conseils donnés par
InitializeSahib
,San
pour activer l'énumération de portée.Si nous voulons également la sécurité de type stricte, le code suivant peut implémenter quelque chose comme
enum
.Le code est modifié à partir de l'exemple de classe Month dans le livre Effective C ++ 3rd: Item 18
la source
Tout d'abord, faites «E» en énumération, «e» en minuscule.
Ensuite, déposez le nom du type «Days» dans «Days.Saturday».
Troisièmement ... achetez-vous un bon livre C ++.
la source