Finora ci siamo occupati per lo più di numeri e stringhe. Per modellare il mondo reale, potremmo voler limitare il numero di valori che una variabile può assumere. Potresti volere un tipo dedicato con pochi valori distinti, ognuno con un nome distinto. Per esempio, in una fabbrica di skateboard, il materiale della tavola potrebbe essere scelto solo tra acero, bambù o plastica.
Potresti usare numeri interi per codificare quei valori, ma dovresti scrivere codice aggiuntivo per controllare se dal sistema arriva un valore non valido per il materiale.
Il significato di quei numeri magici è difficile da seguire nel codice sorgente e si confondono facilmente.
Le enumerations possono essere usate per favorire un codice espressivo e per limitare i confronti sbagliati fatti per distrazione.
Il termine specifico per questo tipo di enumerazione è scoped enumeration.
Lo snippet qui sotto mostra come scrivere una enumeration di nome DeckMaterial.
Nota la parola chiave enum class e il ; alla fine della definizione:
enum class DeckMaterial {
maple,
bamboo,
plastic
};
Ora guarda una funzione che calcola il prezzo nel negozio di skateboard e nota l'operatore di risoluzione dello scope (::) che specifica un enumerator della enumeration:
double deck_price(double base_price, DeckMaterial material) {
if(material == DeckMaterial::plastic) {
return base_price * 0.9;
}
return base_price * 1.3;
}
Immagina di avere una seconda enumeration per il materiale delle ruote:
enum class WheelMaterial {
steel,
clay,
plastic
};
Anche se sia le ruote che la tavola possono essere fatte di plastic, le due non si possono confondere.
Sono tipi diversi: DeckMaterial plastic e WheelMaterial plastic.
Ogni enumeration avrà i suoi enumerators nel proprio scope, il proprio namespace.
Ecco perché si chiamano scoped enumerations.
Potresti pensare che, con un nome come scoped, esistano anche enumerazioni unscoped, e avresti ragione.
Le Unscoped enumerations stanno diventando meno popolari perché condividono tutte lo stesso namespace globale.
Proprio per questa condivisione, non potresti avere due unscoped enumerations con gli stessi enumerators, come plastic nell'esempio qui sopra.
Inoltre, le unscoped enumerations si convertono implicitamente in numeri interi.
Guarda l'esempio qui sotto per un risultato sorprendente:
enum CitrusFruits {
lemons, // 0
oranges, //1
};
enum IceCream {
walnut, // 0
apples, // 1
};
bool comparison{apples == oranges};
// => true
// Example from above:
bool comparison{DeckMaterial::plastic == WheelMaterial::plastic};
// => Does not compile!
Se vuoi convertire le scoped enumerations in numeri interi, puoi usare static_cast<int>.