到目前为止,我们处理的主要是数字和字符串。 为了给现实世界建模,我们可能希望某个变量只能取有限的几个值。 你可能想要一个专门的数据类型,它只包含几个名字各不相同的值。 例如,在滑板工厂里,板面材料只能是枫木、竹子或塑料中的一种。
你可以用整数来编码这些值,但那样就得写额外的代码,去检查系统传来的材料值是不是无效的。
这些魔法数字的含义很难在源码中追查,而且很容易弄混。
用enumerations可以鼓励你写出富有表现力的代码,并减少无意的比较错误。
这种枚举的专门术语叫scoped enumeration。
下面的代码片段展示了如何编写一个DeckMaterial enumeration。
注意enum class关键字,以及定义末尾的;:
enum class DeckMaterial {
maple,
bamboo,
plastic
};
现在来看滑板店里的定价函数,注意作用域解析运算符(::),它指定了来自enumeration的enumerator:
double deck_price(double base_price, DeckMaterial material) {
if(material == DeckMaterial::plastic) {
return base_price * 0.9;
}
return base_price * 1.3;
}
假设你还有第二个enumeration,用来表示轮子材料:
enum class WheelMaterial {
steel,
clay,
plastic
};
尽管轮子和板面都可以用_塑料_制成,但两者不会混淆。
它们是不同的_类型_:DeckMaterial的塑料和WheelMaterial的塑料。
每个enumeration的enumerators都在自己的作用域里,也就是自己的namespace。
这就是它们被称为scoped enumerations的原因。
你可能会想,既然名字里带scoped,那应该也有 unscoped 枚举吧,没错。
Unscoped enumerations越来越不受欢迎,因为它们共享同一个全局命名空间。
正因为共享,你不能有两个unscoped enumerations,它们的enumerators同名,比如上面的例子里的 塑料。
另外,unscoped enumerations会隐式转换为整数。
看看下面这个例子,结果会让你意外:
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!
如果你想把scoped enumerations转换为整数,可以用static_cast<int>。