Hasta ahora hemos trabajado principalmente con números y strings. Para modelar el mundo real, es posible que queramos un número limitado de valores que una variable pueda tomar. Puede que quieras un tipo dedicado con unos pocos valores distintos y con nombres distintos. Por ejemplo, en una fábrica de monopatines, que el material de la tabla sea una elección entre solo arce, bambú o plástico.
Podrías usar números enteros para codificar esos valores, pero tendrías que añadir código extra para comprobar si el sistema devuelve un valor no válido para el material.
El significado de esos números mágicos es difícil de seguir a lo largo del código fuente y son propensos a confusiones.
Las enumerations sirven para fomentar un código expresivo y para limitar las comparaciones erróneas involuntarias.
El término específico para este tipo de enumeración es scoped enumeration.
El fragmento siguiente muestra cómo escribir una enumeration de tipo 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, fíjate en una función de precios de la tienda de monopatines y observa el operador de resolución de scope (::), 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, no se pueden confundir entre sí.
Son tipos distintos: el plastic de DeckMaterial y el plastic de WheelMaterial.
Cada enumeration tendrá sus enumerators en su propio scope, su propio namespace.
Por eso se llaman scoped enumerations.
Puede que estés pensando que, con un nombre como scoped, también debe de haber 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 ese uso compartido, no podrías tener dos unscoped enumerations con los mismos enumerators, como plastic en el ejemplo anterior.
Además, las Unscoped enumerations se convierten implícitamente en números enteros.
Fíjate en el ejemplo siguiente, con 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>.