Até agora, temos lidado sobretudo com números e strings. Para modelar o mundo real, podemos querer um número limitado de valores que uma variável pode assumir. Podes querer um tipo dedicado com alguns valores distintos e nomes distintos. Por exemplo, numa fábrica de skates, ter o material do deck como uma escolha entre apenas ácer, bambu ou plástico.
Podias usar inteiros para codificar esses valores, mas terias de usar código extra para verificar se há um valor inválido vindo do sistema para o material.
O significado desses magic numbers é difícil de seguir pelo código-fonte e são propensos a confusões.
As enumerations podem ser usadas para promover código expressivo e restringir erros de comparação não intencionais.
O termo específico para este tipo de enumeração é scoped enumeration.
O excerto abaixo mostra como escrever uma enumeration DeckMaterial.
Repara na palavra-chave enum class e no ; no fim da definição:
enum class DeckMaterial {
maple,
bamboo,
plastic
};
Agora, olha para uma função de preços na loja de skates e repara no operador de resolução de âmbito (::) que especifica um enumerator da 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 tens uma segunda enumeration para o material das rodas:
enum class WheelMaterial {
steel,
clay,
plastic
};
Embora as rodas e o deck possam ambos ser feitos de plástico, os dois não se podem confundir.
São tipos diferentes: DeckMaterial plastic e WheelMaterial plastic.
Cada enumeration terá os seus enumerators no seu próprio âmbito, o seu próprio namespace.
É por isso que são chamadas scoped enumerations.
Podes estar a pensar que, com um nome como scoped, também existiriam enumerações unscoped, e terias razão.
As Unscoped enumerations estão a tornar-se menos populares porque partilham todos o mesmo namespace global.
Por causa dessa partilha, não podias ter duas unscoped enumerations com os mesmos enumerators como plastic no exemplo acima.
Além disso, as unscoped enumerations convertem-se implicitamente em inteiros.
Olha para o exemplo abaixo para um resultado surpreendente:
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 quiseres converter scoped enumerations em inteiros, podes usar static_cast<int>.