Saltar a contenido

Última actualización:2026-10-12

Tipos de enumeración enum en C++

Sobre el autor:

Cuenta pública personal de WeChat:

wechat

Comportamiento tradicional

Las enumeraciones tienen los problemas siguientes:

  • El ámbito no está restringido, lo que provoca fácilmente conflictos de nombres. Por ejemplo, lo siguiente no llega a compilar:

enum Color
{
    RED,
    BLUE
};
enum Feeling
{
    EXCITED,
    BLUE
};

int main()
{
    Color a = BLUE; // error
    Feeling b = EXCITED;
    std::cout << a << ":" << b << std::endl;
    return 0;
}
```- Se convierten implícitamente a int
- El tipo real que representa a la variable de enumeración no puede especificarse explícitamente, por lo que no se admite la declaración previa de tipos de enumeración.

Para la implementación concreta, consulta: [tradition_color.cpp](https://github.com/Light-City/CPlusPlusThings/tree/master/basic_content/enum/tradition_color.cpp)

## Enfoque clásico

Una forma simple de resolver los conflictos de nombres causados por el ámbito no restringido es añadir un prefijo al nombrar las variables de enumeración, cambiando por ejemplo el caso anterior a COLOR_BLUE y FEELING_BLUE.

En general, por coherencia, añadiríamos el mismo prefijo a todas las constantes. Pero definir así las variables de enumeración resulta pesado. En programas C quizá no quede más remedio. Sin embargo, a quien programa en C++ este método no le gusta nada. La alternativa son los espacios de nombres:
```c++
namespace Color 
{
    enum Type
    {
        RED=15,
        YELLOW,
        BLUE
    };
};
Después de esto ya se puede usar Color::Type c = Color::RED; para definir nuevas variables de enumeración. Si se escribe using namespace Color, el prefijo puede omitirse y el código se simplifica. Sin embargo, como un espacio de nombres puede ampliarse después, el cierre de ámbito que ofrece no es muy fuerte. En proyectos grandes sigue siendo posible que distintas personas den el mismo nombre de tipo de enumeración a cosas distintas.

El método más “eficaz” es usar una clase o una estructura para restringir su ámbito; por ejemplo: la forma de definir nuevas variables es la misma que con el espacio de nombres anterior. Eso sí, así no hay que preocuparse de que la clase se modifique en otro lugar. Aquí se usa una estructura en lugar de una clase porque, de entrada, se quiere que estas constantes sean accesibles públicamente.

struct Color1
{
    enum Type
    {
        RED=102,
        YELLOW,
        BLUE
    };
};
Para la implementación concreta, consulta: classic_practice.cpp

Las clases de enumeración de C++11

El enfoque anterior resuelve el primer problema, pero nada puede hacer con los otros dos. Afortunadamente, el estándar C++11 introdujo las “clases de enumeración” (enum class), que resuelven bastante bien los problemas anteriores.

  • El ámbito del nuevo enum ya no es global
  • No puede convertirse implícitamente a otros tipos

/**
 * @brief C++11的枚举类
 * 下面等价于enum class Color2:int
 */
enum class Color2
{
    RED=2,
    YELLOW,
    BLUE
};
Color2 c2 = Color2::RED;
cout << static_cast<int>(c2) << endl; //必须转!
- Se puede especificar un tipo concreto para almacenar el enum

enum class Color3:char;  // 前向声明

// 定义
enum class Color3:char 
{
    RED='r',
    BLUE
};
char c3 = static_cast<char>(Color3::RED);
Para la implementación concreta, consulta: classic_practice.cpp

Tipos de enumeración dentro de una clase

A veces queremos que ciertas constantes solo sean válidas dentro de una clase. Como las constantes de macro definidas con #define son globales y no sirven para ello, se piensa en usar miembros de datos calificados con const. Y ciertamente los miembros de datos const existen, pero su significado no es el que esperamos.

Un miembro de datos const solo es constante durante la vida de un objeto concreto, pero para la clase entera es variable, porque la clase puede crear varios objetos y el valor del miembro de datos const puede ser distinto en cada uno.

No se puede inicializar un miembro de datos const en la declaración de la clase. El uso siguiente es erróneo, porque mientras no se cree el objeto de la clase el compilador no sabe cuánto vale SIZE. (antes del estándar C++11)

class A 
{
  const int SIZE = 100;   // 错误,企图在类声明中初始化 const 数据成员 
  int array[SIZE];  // 错误,未知的 SIZE 
}; 
Lo correcto es hacerlo en la lista de inicialización del constructor de la clase:

class A 
{
  A(int size);  // 构造函数 
  const int SIZE ;    
}; 
A::A(int size) : SIZE(size)  // 构造函数的定义
{ 

} 
A  a(100); // 对象 a 的 SIZE 值为 100 
A  b(200); // 对象 b 的 SIZE 值为 200 
¿Cómo se puede establecer una constante que sea fija para toda la clase?

No cuentes con los miembros de datos const; debe hacerse con constantes de enumeración dentro de la clase. Por ejemplo:

class Person{
public:
    typedef enum {
        BOY = 0,
        GIRL
    }SexType;
};
//访问的时候通过,Person::BOY或者Person::GIRL来进行访问。
Las constantes de enumeración no ocupan espacio de almacenamiento del objeto; se evalúan todas en tiempo de compilación.

El inconveniente de las constantes de enumeración es que su tipo de datos implícito es entero, su valor máximo es limitado y no puede representar números en coma flotante.

Temas relacionados

Comentarios