Menu
Coddy logo textTech

Enum class e tipizzazione forte

Fa parte della sezione Programmazione orientata agli oggetti del percorso C++ di Coddy. Lezione 80 di 104.

C++11 ha introdotto le enum class (chiamate anche enumerazioni con ambito) per affrontare i limiti delle tradizionali enumerazioni in stile C. Offrono una maggiore sicurezza dei tipi e impediscono l'uso improprio accidentale dei valori dell'enumerazione.

Gli enum tradizionali presentano dei problemi: i loro valori si riversano nell'ambito circostante e vengono convertiti implicitamente in interi, causando bug difficili da individuare:

// enum tradizionale - problematico
enum Color { Red, Green, Blue };
enum TrafficLight { Red, Yellow, Green };  // Errore! Red e Green sono già definiti

int x = Red;  // Si converte implicitamente in int (0)
if (Red == 0) { }  // Si compila - confronto tra enum e int

Le classi enum risolvono questi problemi definendo l'ambito dei valori e impedendo le conversioni implicite:

enum class Color { Red, Green, Blue };
enum class TrafficLight { Red, Yellow, Green };  // OK - nessun conflitto

Color c = Color::Red;      // È necessario usare l'operatore di risoluzione dell'ambito
// int x = c;              // Errore! Nessuna conversione implicita
int x = static_cast<int>(c);  // È necessaria una conversione esplicita

// if (c == 0) { }         // Errore! Non è possibile confrontare con int
if (c == Color::Red) { }   // OK - confronto tra tipi uguali

Puoi anche specificare il tipo sottostante per controllare la memoria:

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

Le classi enum si integrano bene con le progettazioni OOP, rendono il codice più leggibile e rilevano gli errori di tipo in fase di compilazione anziché a runtime.

challenge icon

Sfida

Facile

Costruiamo un sistema di priorità per le attività che usa classi enum per rappresentare i diversi livelli di priorità e gli stati delle attività. Questo dimostra come le classi enum garantiscano la sicurezza dei tipi e prevengano i tipi di bug che si verificano con gli enum tradizionali.

Organizzerai il codice in tre file:

  • TaskTypes.h: definisci le classi enum per il sistema di attività.

    Crea una classe enum Priority con i valori: Low, Medium, High e Critical. Specifica int come tipo sottostante, con i valori rispettivamente 1, 2, 3 e 4.

    Crea una classe enum Status con i valori: Pending, InProgress e Completed.

    Fornisci due funzioni di supporto:

    • priorityToString(Priority p): restituisce la priorità come stringa ("Low", "Medium", "High", o "Critical")
    • statusToString(Status s): restituisce lo stato come stringa ("Pending", "InProgress", o "Completed")
  • Task.h: definisci una classe Task che utilizza le classi enum.

    La classe Task deve memorizzare un nome (stringa), una Priority e uno Status. Il costruttore deve accettare un nome e una priorità, mentre lo stato deve avere come valore predefinito Status::Pending.

    Implementa questi metodi:

    • setStatus(Status s): aggiorna lo stato dell'attività
    • getPriorityValue(): restituisce il valore intero sottostante della priorità usando static_cast
    • display(): stampa l'attività nel formato: [name] - Priority: [priority] (Value: [value]) - Status: [status]
  • main.cpp: leggi tre input:
    1. Nome dell'attività (stringa)
    2. Livello di priorità come intero (1=Low, 2=Medium, 3=High, 4=Critical)
    3. Stato come intero (0=Pending, 1=InProgress, 2=Completed)

    Crea una Task con il nome e la priorità specificati (converti l'intero nel valore enum Priority appropriato usando static_cast). Poi imposta lo stato in base al terzo input. Infine, chiama display() per mostrare i dettagli dell'attività.

Per esempio, con gli input Fix bug, 3 e 1:

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

Con gli input Write docs, 1 e 2:

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

Con gli input Deploy app, 4 e 0:

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

Nota come le classi enum mantengano i valori di priorità e stato completamente separati. Non puoi confrontare accidentalmente una Priority con uno Status né assegnare l'una all'altro. L'uso esplicito di static_cast, necessario per convertire tra interi e valori enum, rende chiaro l'intento del codice e previene bug difficili da individuare.

Provalo tu

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

using namespace std;

int main() {
    // Leggi i dati di input
    string taskName;
    int priorityInt;
    int statusInt;
    
    getline(cin, taskName);
    cin >> priorityInt;
    cin >> statusInt;
    
    // TODO: Crea un Task con il nome e la priorità specificati
    // Usa static_cast per convertire priorityInt nell'enum Priority
    
    // TODO: Imposta lo stato dell'attività in base a statusInt
    // Usa static_cast per convertire statusInt nell'enum Status
    
    // TODO: Chiama display() per mostrare i dettagli dell'attività
    
    return 0;
}
quiz iconMettiti alla prova

Questa lezione include un breve quiz. Inizia la lezione per rispondere e tenere traccia dei tuoi progressi.

Tutte le lezioni di Programmazione orientata agli oggetti

Esercitati da solo: Compilatore C++ online