Menu
Coddy logo textTech

Enum Classes y tipado fuerte

Parte de la sección Programación Orientada a Objetos del Journey de C++ de Coddy — lección 80 de 104.

C++11 introdujo enum classes (también llamadas enumeraciones con ámbito) para abordar las deficiencias de los enums tradicionales al estilo C. Proporcionan una seguridad de tipos más sólida y evitan el uso indebido accidental de los valores de enumeración.

Los enums tradicionales tienen problemas: sus valores se filtran al ámbito circundante y se convierten implícitamente en enteros, lo que provoca errores sutiles:

// Enum tradicional - problemático
enum Color { Red, Green, Blue };
enum TrafficLight { Red, Yellow, Green };  // ¡Error! Red y Green ya están definidos

int x = Red;  // Se convierte implícitamente a int (0)
if (Red == 0) { }  // Compila - comparando enum con int

Las clases Enum resuelven estos problemas al delimitar el alcance de los valores y evitar conversiones implícitas:

enum class Color { Red, Green, Blue };
enum class TrafficLight { Red, Yellow, Green };  // OK - sin conflicto

Color c = Color::Red;      // Debe usar el operador de alcance
// int x = c;              // ¡Error! Sin conversión implícita
int x = static_cast<int>(c);  // Se requiere conversión explícita

// if (c == 0) { }         // ¡Error! No se puede comparar con int
if (c == Color::Red) { }   // OK - comparando los mismos tipos

También puedes especificar el tipo subyacente para el control de memoria:

enum class Status : uint8_t {
    Inactive = 0,
    Active = 1,
    Pending = 2
};

Las clases Enum se integran bien con los diseños de POO, lo que hace que el código sea más legible y permite detectar errores de tipo en tiempo de compilación en lugar de en tiempo de ejecución.

challenge icon

Desafío

Fácil

Vamos a construir un sistema de prioridad de tareas que utiliza enum classes para representar diferentes niveles de prioridad y estados de tareas. Esto demuestra cómo las enum classes proporcionan seguridad de tipos y previenen los tipos de errores que ocurren con los enums tradicionales.

Organizarás tu código en tres archivos:

  • TaskTypes.h: Define tus enum classes para el sistema de tareas.

    Crea una enum class Priority con los valores: Low, Medium, High y Critical. Especifica int como el tipo subyacente, con los valores 1, 2, 3 y 4 respectivamente.

    Crea una enum class Status con los valores: Pending, InProgress y Completed.

    Proporciona dos funciones auxiliares:

    • priorityToString(Priority p) — devuelve la prioridad como un string ("Low", "Medium", "High" o "Critical")
    • statusToString(Status s) — devuelve el estado como un string ("Pending", "InProgress" o "Completed")
  • Task.h: Define una clase Task que utilice tus enum classes.

    Tu Task debe almacenar un nombre (string), una Priority y un Status. El constructor debe recibir un nombre y una prioridad, con el estado por defecto en Status::Pending.

    Implementa estos métodos:

    • setStatus(Status s) — actualiza el estado de la tarea
    • getPriorityValue() — devuelve el valor entero subyacente de la prioridad utilizando static_cast
    • display() — imprime la tarea en el formato: [name] - Priority: [priority] (Value: [value]) - Status: [status]
  • main.cpp: Lee tres entradas:
    1. Nombre de la tarea (string)
    2. Nivel de prioridad como entero (1=Low, 2=Medium, 3=High, 4=Critical)
    3. Estado como entero (0=Pending, 1=InProgress, 2=Completed)

    Crea una Task con el nombre y la prioridad dados (convierte el entero al valor de enum Priority apropiado usando static_cast). Luego, establece su estado basándote en la tercera entrada. Finalmente, llama a display() para mostrar los detalles de la tarea.

Por ejemplo, con las entradas Fix bug, 3 y 1:

Fix bug - Priority: High (Value: 3) - Status: InProgress

Con las entradas Write docs, 1 y 2:

Write docs - Priority: Low (Value: 1) - Status: Completed

Con las entradas Deploy app, 4 y 0:

Deploy app - Priority: Critical (Value: 4) - Status: Pending

Observa cómo las enum classes mantienen los valores de prioridad y estado completamente separados; no puedes comparar accidentalmente una Priority con un Status ni asignar uno al otro. El static_cast explícito requerido para convertir entre enteros y valores de enum hace que la intención del código sea clara y evita errores sutiles.

Pruébalo tú mismo

#include <iostream>
#include <string>
#include "Task.h"

using namespace std;

int main() {
    // Leer entradas
    string taskName;
    int priorityInt;
    int statusInt;
    
    getline(cin, taskName);
    cin >> priorityInt;
    cin >> statusInt;
    
    // TODO: Crear una Task con el nombre y la prioridad dados
    // Usar static_cast para convertir priorityInt al enum Priority
    
    // TODO: Establecer el estado de la tarea basado en statusInt
    // Usar static_cast para convertir statusInt al enum Status
    
    // TODO: Llamar a display() para mostrar los detalles de la tarea
    
    return 0;
}
quiz iconPonte a prueba

Esta lección incluye un breve cuestionario. Empieza la lección para responderlo y registrar tu progreso.

Todas las lecciones de Programación Orientada a Objetos