Menu
Coddy logo textTech

Enum Classes e Tipagem Forte

Parte da seção Programação Orientada a Objetos do Journey de C++ da Coddy — lição 80 de 104.

O C++11 introduziu enum classes (também chamadas de enumerações com escopo) para resolver as deficiências dos enums tradicionais no estilo C. Elas fornecem uma segurança de tipo mais forte e evitam o uso indevido acidental de valores de enumeração.

Enums tradicionais têm problemas: seus valores vazam para o escopo circundante e se convertem implicitamente em inteiros, levando a bugs sutis:

// Enum tradicional - problemático
enum Color { Red, Green, Blue };
enum TrafficLight { Red, Yellow, Green };  // Erro! Red e Green já definidos

int x = Red;  // Converte implicitamente para int (0)
if (Red == 0) { }  // Compila - comparando enum com int

As classes Enum resolvem esses problemas ao definir o escopo dos valores e impedir conversões implícitas:

enum class Color { Red, Green, Blue };
enum class TrafficLight { Red, Yellow, Green };  // OK - sem conflito

Color c = Color::Red;      // Deve usar o operador de escopo
// int x = c;              // Erro! Sem conversão implícita
int x = static_cast<int>(c);  // Conversão explícita necessária

// if (c == 0) { }         // Erro! Não é possível comparar com int
if (c == Color::Red) { }   // OK - comparando os mesmos tipos

Você também pode especificar o tipo subjacente para controle de memória:

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

Classes Enum integram-se bem com designs de POO, tornando o código mais legível e capturando erros de tipo em tempo de compilação em vez de tempo de execução.

challenge icon

Desafio

Fácil

Vamos construir um sistema de prioridade de tarefas que utiliza enum classes para representar diferentes níveis de prioridade e status de tarefas. Isso demonstra como as enum classes fornecem segurança de tipo e evitam os tipos de bugs que ocorrem com enums tradicionais.

Você organizará seu código em três arquivos:

  • TaskTypes.h: Defina suas enum classes para o sistema de tarefas.

    Crie uma enum class Priority com os valores: Low, Medium, High e Critical. Especifique int como o tipo subjacente, com os valores 1, 2, 3 e 4, respectivamente.

    Crie uma enum class Status com os valores: Pending, InProgress e Completed.

    Forneça duas funções auxiliares:

    • priorityToString(Priority p) — retorna a prioridade como uma string ("Low", "Medium", "High" ou "Critical")
    • statusToString(Status s) — retorna o status como uma string ("Pending", "InProgress" ou "Completed")
  • Task.h: Defina uma classe Task que utiliza suas enum classes.

    Sua Task deve armazenar um nome (string), uma Priority e um Status. O construtor deve receber um nome e uma prioridade, com o status padrão sendo Status::Pending.

    Implemente estes métodos:

    • setStatus(Status s) — atualiza o status da tarefa
    • getPriorityValue() — retorna o valor inteiro subjacente da prioridade usando static_cast
    • display() — imprime a tarefa no formato: [name] - Priority: [priority] (Value: [value]) - Status: [status]
  • main.cpp: Leia três entradas:
    1. Nome da tarefa (string)
    2. Nível de prioridade como inteiro (1=Low, 2=Medium, 3=High, 4=Critical)
    3. Status como inteiro (0=Pending, 1=InProgress, 2=Completed)

    Crie uma Task com o nome e a prioridade fornecidos (converta o inteiro para o valor de enum Priority apropriado usando static_cast). Em seguida, defina seu status com base na terceira entrada. Por fim, chame display() para mostrar os detalhes da tarefa.

Por exemplo, com as entradas Fix bug, 3 e 1:

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

Com as entradas Write docs, 1 e 2:

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

Com as entradas Deploy app, 4 e 0:

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

Observe como as enum classes mantêm os valores de prioridade e status completamente separados — você não pode comparar acidentalmente uma Priority com um Status ou atribuir um ao outro. O static_cast explícito necessário para converter entre inteiros e valores de enum torna a intenção do código clara e evita bugs sutis.

Folha de consulta

O C++11 introduziu enum classes (enumerações com escopo) para fornecer uma segurança de tipo mais forte do que os enums tradicionais do estilo C.

Enums tradicionais têm problemas com vazamento de escopo e conversões implícitas:

// Traditional enum - problematic
enum Color { Red, Green, Blue };
enum TrafficLight { Red, Yellow, Green };  // Erro! Red e Green já definidos

int x = Red;  // Converte implicitamente para int
if (Red == 0) { }  // Compila - comparando enum com int

Enum classes resolvem esses problemas exigindo resolução de escopo e impedindo conversões implícitas:

enum class Color { Red, Green, Blue };
enum class TrafficLight { Red, Yellow, Green };  // OK - sem conflito

Color c = Color::Red;      // Deve usar o operador de escopo
// int x = c;              // Erro! Sem conversão implícita
int x = static_cast<int>(c);  // Conversão explícita necessária

// if (c == 0) { }         // Erro! Não é possível comparar com int
if (c == Color::Red) { }   // OK - comparando os mesmos tipos

Você pode especificar o tipo subjacente para controle de memória:

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

Para converter entre enum classes e inteiros, use casting explícito:

// Inteiro para enum class
Priority p = static_cast<Priority>(3);

// Enum class para inteiro
int value = static_cast<int>(p);

Experimente você mesmo

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

using namespace std;

int main() {
    // Ler as entradas
    string taskName;
    int priorityInt;
    int statusInt;
    
    getline(cin, taskName);
    cin >> priorityInt;
    cin >> statusInt;
    
    // TODO: Criar uma Task com o nome e prioridade fornecidos
    // Use static_cast para converter priorityInt para o enum Priority
    
    // TODO: Definir o status da tarefa com base em statusInt
    // Use static_cast para converter statusInt para o enum Status
    
    // TODO: Chamar display() para mostrar os detalhes da tarefa
    
    return 0;
}
quiz iconTeste seus conhecimentos

Esta lição inclui um quiz rápido. Comece a lição para respondê-lo e acompanhar seu progresso.

Todas as lições de Programação Orientada a Objetos