web-dev-qa-db-fra.com

Comment utiliser les énumérations en C ++

Supposons que nous ayons une enum semblable à celle-ci:

enum Days {Saturday, Sunday, Tuesday,Wednesday, Thursday, Friday};

Je veux créer une instance de ce enum et l'initialiser avec une valeur appropriée. Je fais donc:

Days day = Days.Saturday;

Maintenant, je veux vérifier ma variable ou instance avec une valeur existante enum, alors je le fais:

if (day == Days.Saturday)
{
    std::cout<<"Ok its Saturday";
}

Ce qui me donne une erreur de compilation:

erreur: expression primaire attendue avant le 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-là font-ils réellement référence, dans la mesure où l'un est OK et l'autre provoque une erreur de compilation?

191
Breeze

Ce code est faux:

enum Days {Saturday, Sunday, Tuesday, Wednesday, Thursday, Friday};
Days day = Days.Saturday;
if (day == Days.Saturday)

Parce que Days n'est ni 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 équivaut à std::string.clear. std::string est un type, vous ne pouvez donc pas utiliser . dessus. Vous utilisez . sur une instance d'une classe.

Malheureusement, les enums sont magiques et l'analogie s'arrête là. Parce qu'avec une classe, vous pouvez utiliser 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). Cela est dû au fait que C++ est (quelque peu) rétro-compatible avec C, et que C n’avait pas d’espaces de noms, les énumérations devaient donc se trouver dans l’espace de noms global. Donc, la syntaxe est simplement:

enum Days {Saturday, Sunday, Tuesday, Wednesday, Thursday, Friday};
Days day = Saturday;
if (day == Saturday)

Heureusement, Mike Seymour observe que cela a été traité en C++ 11. Remplacez enum par enum class et il aura sa propre portée. so Days::Sunday est non seulement valide, mais constitue le moyen uniquement d'accéder à Sunday. Jours heureux!

317
Mooing Duck

Cela sera suffisant pour déclarer votre variable enum et la comparer:

enum Days {Saturday, Sunday, Tuesday, Wednesday, Thursday, Friday};
Days day = Saturday;
if (day == Saturday) {
    std::cout << "Ok its Saturday";
}
24
mathematician1975

Une grande partie de ceci devrait vous donner des erreurs de compilation.

// note the lower case enum keyword
enum Days { Saturday, Sunday, Monday, Tuesday, Wednesday, Thursday, Friday };

Maintenant, Saturday, Sunday, etc. peuvent être utilisés en tant que constantes nues de niveau supérieur, et Days peut être utilisé en tant que type:

Days day = Saturday;   // Days.Saturday is an error

Et pareillement plus tard, pour tester:

if (day == Saturday)
    // ...

Ces valeurs enum ressemblent à des constantes nues - elles sont un - scoped - avec un peu d'aide supplémentaire du compilateur: (sauf si vous ' En utilisant C++ 11 les classes enum ) elles ne sont pas encapsulées comme les membres d'objet ou de structure, par exemple, et vous ne pouvez pas les appeler membres de Days.

Vous aurez ce que vous cherchez avec C++ 11 , qui introduit un enum class:

enum class Days
{
    SUNDAY,
    MONDAY,
    // ... etc.
}

// ...

if (day == Days::SUNDAY)
    // ...

Notez que ce C++ est un peu différent du C de plusieurs façons. L'un d'entre eux est que C requiert l'utilisation du mot clé enum lors de la déclaration d'une variable:

// day declaration in C:
enum Days day = Saturday;
22
pb2q

Vous pouvez utiliser une astuce pour utiliser les portées à votre guise, déclarez simplement enum de la manière suivante:

struct Days 
{
   enum type
   {
      Saturday,Sunday,Tuesday,Wednesday,Thursday,Friday
   };
};

Days::type day = Days::Saturday;
if (day == Days::Saturday)
11
ataman1x

Plutôt que d’utiliser un ensemble d’énoncés if, les enums se prêtent bien pour changer de déclaration

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 à;

if(day == Days.Saturday)
etc

Vous pouvez le faire en C++:

if(day == Days::Saturday)
etc

Voici un exemple très simple:

EnumAppState.h

#ifndef ENUMAPPSTATE_H
#define ENUMAPPSTATE_H
enum eAppState
{
    STARTUP,
    EDIT,
    ZONECREATION,
    SHUTDOWN,
    NOCHANGE
};
#endif

Somefile.cpp

#include "EnumAppState.h"
eAppState state = eAppState::STARTUP;
switch(state)
{
case STARTUP:
    //Do stuff
    break;
case EDIT:
    //Do stuff
    break;
case ZONECREATION:
    //Do stuff
    break;
case SHUTDOWN:
    //Do stuff
    break;
case NOCHANGE:
    //Do stuff
    break;
}
8
Dean Knight

Si vous utilisez encore C++ 03 et souhaitez utiliser des énumérations, vous devriez les utiliser à l'intérieur d'un espace de noms. Par exemple:

namespace Daysofweek{
enum Days {Saturday, Sunday, Tuesday,Wednesday, Thursday, Friday};
}

Vous pouvez utiliser l'énum en dehors de l'espace de noms comme,

Daysofweek::Days day = Daysofweek::Saturday;

if (day == Daysofweek::Saturday)
{
    std::cout<<"Ok its Saturday";
}
6
San

Cela ne devrait pas fonctionner en C++:

Days.Saturday

Jours n'est pas une étendue ou un objet contenant des membres auxquels vous pouvez accéder avec l'opérateur point. Cette syntaxe est juste un C # -ism 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 de portée:

enum E { A, B, C };

A;
E::B; // works with Microsoft's extension

Mais ceci est non standard avant C++ 11. En C++ 03, les identificateurs déclarés dans une énumération n'existent que dans la même portée que le type énuméré lui-même.

A;
E::B; // error in C++03

C++ 11 permet de qualifier les identificateurs enum avec le nom enum, et introduit également les classes enum, qui créent une nouvelle portée pour les identificateurs au lieu de les placer dans la portée environnante.

A;
E::B; // legal in C++11

enum class F { A, B, C };

A; // error
F::B;
6
bames53

Vous recherchez Énumérations fortement typées , une fonctionnalité disponible en C++ 11 standard. Il transforme les énumérations en classes avec des valeurs de portée.

En utilisant votre propre exemple de code, il est:

  enum class Days {Saturday, Sunday, Tuesday,Wednesday, Thursday, Friday};
  Days day = Days::Saturday;

  if (day == Days::Saturday)  {
    cout<<" Today is Saturday !"<<endl;
  }
  //int day2 = Days::Sunday; // error ! invalid 

L'utilisation de :: comme accesseurs d'énumérations échouera si la cible est une norme C++ antérieure à C++ 11. Mais certains anciens compilateurs ne le supportaient pas, de même que certains IDE surchargent simplement cette option et définissent un ancien C++ std.

Si vous utilisez gcc, activez C + 11 avec - std = c ++ 11 ou - std = gnu11.

Soyez heureux !

4
Alex Byrth

Les énumérations en C++ sont comme des entiers masqués par les noms que vous leur donnez, lorsque vous déclarez vos valeurs enum (ce n'est pas une définition, mais un indice sur son fonctionnement).

Mais il y a deux erreurs dans votre code:

  1. Sort enum tout en minuscule
  2. Vous n'avez pas besoin du Days. avant samedi.
  3. Si cette énumération est déclarée dans une classe, utilisez if (day == YourClass::Saturday){}
3
Balázs Édes

Malheureusement, les éléments de l'énum sont "globaux". Vous y accédez en faisant day = Saturday. Cela signifie que vous ne pouvez pas avoir enum A { a, b } ; et enum B { b, a } ; car ils sont en conflit.

3
Grzegorz

Tandis que C++ (à l'exception de C++ 11) a des énumérations, leurs valeurs sont "filtrées" dans l'espace de noms global.
Si vous ne voulez pas qu’ils fuient (et n’avez PAS besoin d’utiliser le type enum), tenez compte des points suivants:

class EnumName {  
   public:   
      static int EnumVal1;  
      (more definitions)  
};  
EnumName::EnumVal1 = {value};  
if ([your value] == EnumName::EnumVal1)  ...
2
InitializeSahib

Je pense que votre problème fondamental est l'utilisation de . à la place de ::, qui utilisera l'espace de noms.

Essayer:

enum Days {Saturday, Sunday, Tuesday, Wednesday, Thursday, Friday};
Days day = Days::Saturday;
if(Days::Saturday == day)  // I like literals before variables :)
{
    std::cout<<"Ok its Saturday";
}
1
James Oravec