Murilo :P

C++, Computação, Programação, Web e afins :)

O que são enums e como utilizá-los melhor em C++

with 16 comments

C++

O que são os enums (C e C++)

Um enum (enumeração) é um tipo definido pelo usuário (programador) que consiste em constantes do tipo int nomeadas.

Um jeito tradicional de se declarar constantes em C e C++ é o seguinte:

#define BRASIL 0
#define ITALIA 1
#define PORTUGAL 2
#define ALEMANHA 3

E eis a maneira de fazer o mesmo utilizando enums:

enum
{
        BRASIL,
        ITALIA,
        PORTUGAL,
        ALEMANHA
};

Pode-se, alternativamente, criar um tipo para seu enum:

enum Paises
{
        BRASIL,
        ITALIA,
        PORTUGAL,
        ALEMANHA
};

E declarar uma variável desse tipo com:

Paises pais; //C++ apenas
enum Paises pais; //C e C++

Num enum igual a esses acima, a primeira constante recebe o valor 0 e as subsequentes recebem o valor da constante anterior mais 1. Ou seja, BRASIL é 0, ITALIA é 1, PORTUGAL é 2 e ALEMANHA é 3.
Podemos também atribuir valores manualmente às constantes como em:

enum Paises
{
        BRASIL = 2,
        ITALIA,  //ITALIA é igual a 3 (2 + 1)
        PORTUGAL = 1,
        ALEMANHA  //ALEMANHA é igual a 2 (1 + 1)
};

Como podemos perceber no exemplo anterior, a mesma regra se aplica para os enums com valores manuais, o que não tiver um valor explicitamente inserido receberá o valor do anterior somado em 1. Percebemos também que podem haver constantes com o mesmo valor (BRASIL == ALEMANHA == 2).

Conversão

A conversão de uma constante de um enum para um inteiro por exemplo é feita automaticamente. Já o contrário não deve ser permitido pelo compilador.

enum Paises
{
        BRASIL,
        ARGENTINA,
        VENEZUELA
};

...

int inteiro = VENEZUELA + 2; //4
Paises pais = 3; //ERRO

Uma melhor maneira de usar enums em C++

Veja o exemplo:

enum Paises
{
        BRASIL,
        ITALIA,
        ALEMANHA
};

enum Uvas
{
        RUBI,
        ITALIA,
        UMOUTROTIPODEUVA
};

Isso irá ocasionar um erro porque ITALIA já foi definido. A saida do meu compilador (g++ 4.3.2) foi a seguinte:

murilo@blacksheep:~/$ g++ enums.cpp
enums.cpp:14: error: conflicting declaration ‘ITALIA’
enums.cpp:8: error: ‘
ITALIA’ has a previous declaration as ‘Paises ITALIA’

Mas e agora?? Eu quero ter dois enums diferentes que representam coisas diferentes mas que podem ter a mesma constante. Como?

A resposta é namespaces!
Em C++ podemos declarar nossos enums dentro de namespaces e assim termos as constantes em espaços de nomes diferentes. Nada de conflito agora hein g++!!!

namespace Paises
{
enum
{
BRASIL,
ITALIA,
ALEMANHA
};
}

namespace Uvas
{
enum
{
RUBI,
ITALIA,
UMOUTROTIPODEUVA
};
}

//*…*//
//Modo de uso:

std::cout << Uvas::ITALIA; std::cout << Paises::ITALIA; [/code] É isso aí galera, até a próxima.

Written by Murilo Adriano

29 de May de 2009 at 01:28

Posted in C/C++, Programação

Tagged with , , ,

16 Responses

Subscribe to comments with RSS.

  1. “Nada de conflito agora, ein g++!” kkkkkkk³
    Apesar de você já ter me explicado isso e eu já ter visto em um código que eu ajudei a desenvolver, não entendo bem.
    =x
    Mas, quem acredita sempre alcança, não é?
    Ainda irei entender.

    Eduardo

    31 de May de 2009 at 20:50

  2. Hehehe, é isso aí!
    Perseverança!

    Murilo Adriano

    15 de June de 2009 at 23:25

  3. Ótimo artigo, muito obrigado.

    Anonimo

    25 de July de 2009 at 18:41

  4. […] com um comentário Mais uma trick com enums. […]

  5. Ainda há uma dúvida.

    Se eu tiver uma string em mãos, dentro de uma variavel qualquer, como posso saber se essa string pode ser ou não um dos elementos do meu Enum?

    Por exemplo:

    string s = “ITALIA”;

    Como saber se s pertence ao ENUM?

    Lucas

    19 de September de 2009 at 01:43

    • Opa Lucas, desculpe-me pela demora. Ando muito ocupado ultimamente.
      Enums são tipos enumerados numéricos, então não tem como comparar diretamente.
      O que você pode fazer é o seguinte:

      Você pode fazer algo como comparar o valor da string e obter o enum correspondente e trabalhar corretamente com esses enums.

      Abração Lucas, valeu!

      Murilo Adriano

      23 de September de 2009 at 09:24

  6. Muito bom artigo, obrigado por compartilhar, me ajudou muito!

    Yuri Souza Padua

    15 de October de 2009 at 02:41

  7. Seria uma boa voce por ai um switch case usando os enuns… até eu saber que o trem era mais usado em ‘cases’ foi um parto kk

    Lucas P. Caixeta

    6 de January de 2011 at 13:01

  8. Um enum pode ter mais de um valor? Em java, por exemplo, pode-se ter:

    enum Pais {
    BRASIL(1, “Brasil”), ITALIA (2, “Itália”);
    private int codigo;
    private String nome;
    public Pais(int codigo, String nome) { this.codigo = codigo; this.nome = nome; }
    }

    Qual a alternativa em C++?

    Otto

    28 de March de 2011 at 19:56

    • Olá Otto, podemos simular o comportamento criando uma classe como a seguinte:


      class Pais {
      public:
      // definidos depois
      static const Pais BRASIL;
      static const Pais ITALIA;
      // ...

      private:
      int codigo;
      std::string nome;

      private: // pode ser public se quiser que o usuário possa instanciar essa classe para outros objetos
      Pais(int codigo, std::string nome) {
      this->codigo = codigo;
      this->nome = mome;
      }

      public:
      // Propriedades e funções-membro
      };

      // Definições:
      const Pais Pais::BRASIL = Pais(1, "Brasil");
      const Pais Pais::ITALIA = Pais(2, "Itália");

      Se quiser ver mais ideias: http://stackoverflow.com/questions/1965249/how-to-write-java-like-enums-in-c

      Murilo Adriano

      28 de March de 2011 at 20:14

  9. Fiz um enum igual ao seu Pais. E tenho o código (da lib UnitTest++):

    CHECK_EQUAL(Pais::BRASIL, paises.getPais(1)); // getPais retorna int.

    error: no matching function for call to ‘CheckEqual(UnitTest::TestResults&, Pais::, int, UnitTest::TestDetails)’

    O Pais::BRASIL não deveria ser convertido a int?

    Otto

    29 de March de 2011 at 19:54

    • Acho que o wordpress entendeu uma parte da mensagem de erro como se fosse HTML. Deveria ser Pais::(anonymous enum), com maior que/menor que no lugar dos parênteses.

      Otto

      29 de March de 2011 at 19:57

      • Nunca usei essa biblioteca de testes mas creio que basta você implementar os operator==. Recomendo que você implemente todos os operadores relacionais (>=, >, etc) se quiser algo bem próximo de um enum mesmo. Ainda recomendo que você implemente como abaixo o operator int() que é o operador que é chamado quando você faz uma conversão para int (um cast). Segue o código:

        public: // Na parte public da sua classe:
        operator int() const
        {
        return codigo;
        }

        bool operator==(int a) const
        {
        return codigo == a;
        }

        Qualquer coisa, estamos aí!

        Murilo Adriano

        30 de March de 2011 at 08:37

  10. eu deixo um desafio, entrem na pagina
    http://www.dsc.ufcg.edu.br/~rangel/tp/downloads/Guia%20de%20Laboratorio%2001%202011.2%20T1.pdf.

    e tentem resolver o exercicio 2 que trata de enums, essa lista foi passada para os alunos de engenharia eletrica da UFCG.

    boa sorte

    Lucas

    10 de September de 2011 at 17:14

  11. Muito bom, tirei minha duvida.

    Renato Santos

    24 de March de 2013 at 12:24


Leave a reply to Murilo Adriano Cancel reply