Hasta ahora hemos manejado sobre todo números y strings. Para modelar el mundo real, puede que queramos un número limitado de valores que una variable pueda tomar. Quizá quieras un tipo dedicado con unos pocos valores distintos y nombres distintos. Por ejemplo, en una fábrica de patinetas, que el material de la tabla sea una elección entre solo maple, bamboo o plastic.
Podrías usar números enteros para codificar esos valores, pero tendrías que usar código adicional para verificar si llega del sistema un valor no válido para el material.
El significado de esos números mágicos es difícil de rastrear a lo largo del código fuente y se prestan a confusiones.
Las enumerations se pueden usar para fomentar un código expresivo y para restringir errores de comparación involuntarios.
El término específico para este tipo de enumeración es scoped enumeration.
El siguiente fragmento muestra cómo escribir una enumeration DeckMaterial.
Fíjate en la palabra clave enum class y en el ; al final de la definición:
enum class DeckMaterial {
maple,
bamboo,
plastic
};
Ahora observa una función de precios en la tienda de patinetas y fíjate en el operador de resolución de ámbito (::) que especifica un enumerator de la enumeration:
double deck_price(double base_price, DeckMaterial material) {
if(material == DeckMaterial::plastic) {
return base_price * 0.9;
}
return base_price * 1.3;
}
Imagina que tienes una segunda enumeration para el material de las ruedas:
enum class WheelMaterial {
steel,
clay,
plastic
};
Aunque tanto las ruedas como la tabla pueden ser de plastic, los dos no se pueden confundir.
Son tipos distintos: DeckMaterial plastic y WheelMaterial plastic.
Cada enumeration tendrá sus enumerators en su propio ámbito, en su propio namespace.
Por eso se llaman scoped enumerations.
Quizá estés pensando que con un nombre como scoped también habría enumeraciones unscoped, y tienes razón.
Las Unscoped enumerations son cada vez menos populares porque todas comparten el mismo espacio de nombres global.
Debido a esa compartición, no podrías tener dos unscoped enumerations con los mismos enumerators como plastic en el ejemplo de arriba.
Además, las unscoped enumerations se convierten implícitamente en números enteros.
Mira el ejemplo de abajo para ver un resultado 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!
Si quieres convertir scoped enumerations en números enteros, puedes usar static_cast<int>.