Classes Enum 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 as classes enum (também chamadas de enumerações com escopo) para resolver as deficiências dos enums tradicionais no estilo C. Elas oferecem uma segurança de tipos mais robusta e evitam o uso acidentalmente incorreto dos valores de enumeração.
Enums tradicionais apresentam problemas: seus valores vazam para o escopo circundante e são convertidos 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 intClasses enum resolvem esses problemas ao delimitar 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 tiposVocê também pode especificar o tipo subjacente para controlar a memória:
enum class Status : uint8_t {
Inactive = 0,
Active = 1,
Pending = 2
};As classes enum se integram bem aos projetos de POO, tornando o código mais legível e detectando erros de tipo em tempo de compilação, em vez de em tempo de execução.
Desafio
FácilVamos criar um sistema de prioridade de tarefas que usa classes enum para representar diferentes níveis de prioridade e status de tarefas. Isso demonstra como as classes enum fornecem segurança de tipos e evitam os tipos de bugs que ocorrem com enums tradicionais.
Você organizará seu código em três arquivos:
TaskTypes.h: Defina suas classes enum para o sistema de tarefas.Crie uma classe enum
Prioritycom os valores:Low,Medium,HigheCritical. Especifiqueintcomo o tipo subjacente, com os valores 1, 2, 3 e 4, respectivamente.Crie uma classe enum
Statuscom os valores:Pending,InProgresseCompleted.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 classeTaskque use suas classes enum.Sua
Taskdeve armazenar um nome (string), umaPrioritye umStatus. O construtor deve receber um nome e uma prioridade, com o status tendo como padrãoStatus::Pending.Implemente estes métodos:
setStatus(Status s): atualiza o status da tarefagetPriorityValue(): retorna o valor inteiro subjacente da prioridade usandostatic_castdisplay(): exibe a tarefa no formato:[name] - Priority: [priority] (Value: [value]) - Status: [status]
main.cpp: Leia três entradas:- Nome da tarefa (string)
- Nível de prioridade como inteiro (1=Low, 2=Medium, 3=High, 4=Critical)
- Status como inteiro (0=Pending, 1=InProgress, 2=Completed)
Crie uma
Taskcom o nome e a prioridade fornecidos (converta o inteiro para o valor apropriado do enumPriorityusandostatic_cast). Em seguida, defina seu status com base na terceira entrada. Por fim, chamedisplay()para mostrar os detalhes da tarefa.
Por exemplo, com as entradas Fix bug, 3 e 1:
Fix bug - Priority: High (Value: 3) - Status: InProgressCom as entradas Write docs, 1 e 2:
Write docs - Priority: Low (Value: 1) - Status: CompletedCom as entradas Deploy app, 4 e 0:
Deploy app - Priority: Critical (Value: 4) - Status: PendingObserve como as classes enum mantêm os valores de prioridade e status completamente separados. Você não pode comparar acidentalmente uma Priority com um Status nem atribuir uma à outra. O static_cast explícito necessário para converter entre inteiros e valores de enum torna clara a intenção do código e evita bugs sutis.
Experimente você mesmo
#include <iostream>
#include <string>
#include "Task.h"
using namespace std;
int main() {
// Ler entradas
string taskName;
int priorityInt;
int statusInt;
getline(cin, taskName);
cin >> priorityInt;
cin >> statusInt;
// TODO: Crie um Task com o nome e a prioridade fornecidos
// Use static_cast para converter priorityInt para o enum Priority
// TODO: Defina o status da task com base em statusInt
// Use static_cast para converter statusInt para o enum Status
// TODO: Chame display() para mostrar os detalhes da task
return 0;
}
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
1Fundamentos de POO
Arquivos externosBuild e compilação em C++Arquivos de cabeçalho e arquivos-fonteNamespaces e escopoIntrodução à POO em C++Classes vs. objetosO ponteiro 'this'Métodos (funções membro)Atributos (membros de dados)Noções básicas de construtores e destruidoresRevisão - calculadora simples4Propriedades de Classe
Membros de Instância vs. EstáticosGetters e SettersFunções Membro ConstPalavra-chave MutableMétodos e Variáveis EstáticosFunções e Classes FriendRevisão - Gerenciador de Contas Bancárias7Herança
Herança básicaNíveis de acesso da herançaOrdem de chamada de construtor e destrutorSobrescrita de métodosFunções virtuais e VTableHerança múltiplaHerança virtualRevisão - Hierarquia de funcionários10Visão geral da STL
Visão geral e filosofia da STLContêineres da STLIteradoresAlgoritmos da STLFunctors e expressões lambdaRecapitulação - Frequência de palavras13Padrões de Projeto — Parte 1
Introdução aos Padrões de ProjetoPadrão SingletonFactory e Abstract FactoryPadrão BuilderPadrão ObserverPadrão Strategy2Gerenciamento de Memória
Memória Stack vs. HeapPonteiros e ReferênciasMemória Dinâmica (new/delete)Ponteiros Inteligentes em C++RAII em C++Revisão - Gerenciador de Array Dinâmico5Encapsulamento
Especificadores de acesso em C++Especificadores de acesso em profundidadeOcultação de informaçõesStruct vs ClasseClasses aninhadas e internasRecapitulação - Sistema de registros de alunos8Polimorfismo
Polimorfismo em compilação vs. execuçãoSobrecarga de funçõesFunções virtuais revisadasFunções virtuais purasClasses abstratasDesign de interfaces em C++Conversão dinâmica e RTTIRecapitulação — Calculadora de formas11Conceitos Avançados de OOP
Composição vs. HerançaMixins via CRTPIdioma PimplApagamento de TiposClasses Enum e Tipagem ForteTratamento de Exceções em OOPHierarquias de Exceções Personalizadas14Padrões de Projeto — Parte 2
Padrão CommandPadrão AdapterPadrão DecoratorPadrão Template MethodPadrão StatePadrão CompositeRAII como Padrão3Construtores e Destrutores
Construtor PadrãoConstrutor ParametrizadoConstrutor de CópiaConstrutor de MovimentoListas de Inicialização do ConstrutorConstrutores DelegantesAprofundamento em DestrutoresRegra dos Três / Cinco / ZeroRevisão - Classe String6Sobrecarga de Operadores
Introdução à Sobrecarga de OperadoresSobrecarga de Operadores AritméticosSobrecarga de Operadores de ComparaçãoOperadores de FluxoSobrecarga do Operador de AtribuiçãoSobrecarga dos Operadores [] e ()Operadores de Conversão de TipoRecapitulação - Classe Matrix9Templates
Templates de FunçõesTemplates de ClassesEspecialização de TemplatesTemplates VariádicosNoções Básicas de SFINAE e Traits de TiposRecapitulação - Contêiner GenéricoPratique por conta própria: Compilador de C++ online