为什么枚举类优先于普通枚举?
我听到一些人build议在C ++中使用枚举类 ,因为它们的types安全 。
但是这到底意味着什么呢?
 C ++有两种enum : 
-   enum classes
-  平原enum
以下是一些如何声明它们的例子:
  enum class Color { red, green, blue }; // enum class enum Animal { dog, cat, bird, human }; // plain enum 
两者有什么区别?
- 
enum classes – 枚举器名称是枚举的本地和它们的值不隐式转换为其他types(如另一个enum或int)
- 
Plain enums – 枚举器名称与枚举的范围相同,并且它们的值隐式转换为整数和其他types
例:
 enum Color { red, green, blue }; // plain enum enum Card { red_card, green_card, yellow_card }; // another plain enum enum class Animal { dog, deer, cat, bird, human }; // enum class enum class Mammal { kangaroo, deer, human }; // another enum class void fun() { // examples of bad use of plain enums: Color color = Color::red; Card card = Card::green_card; int num = color; // no problem if (color == Card::red_card) // no problem (bad) cout << "bad" << endl; if (card == Color::green) // no problem (bad) cout << "bad" << endl; // examples of good use of enum classes (safe) Animal a = Animal::deer; Mammal m = Mammal::deer; int num2 = a; // error if (m == a) // error (good) cout << "bad" << endl; if (a == Mammal::deer) // error (good) cout << "bad" << endl; } 
结论:
  enum class es应该是首选,因为它们导致更less的可能导致错误的意外。 
来自Bjarne Stroustrup的C ++ 11 FAQ :
enum classes(“new enums”,“strong enums”)解决了传统C ++枚举的三个问题:
- 常规枚举隐式转换为int,导致错误,当有人不希望枚举作为一个整数。
- 常规枚举将其枚举器导出到周围的范围,导致名称冲突。
- 不能指定
enum的基础types,导致混淆,兼容性问题,并使前向声明变得不可能。新枚举是“枚举类”,因为它们将传统枚举(名称值)的方面与类(范围成员和缺乏转换)的方面结合在一起。
所以,正如其他用户所说,“强枚举”会使代码更安全。
  “经典” enum的基础types应该是一个足够大的整数types,以适应enum所有值; 这通常是一个int 。 同样,每个枚举types应该与char或有符号/无符号整数types兼容。 
 这是一个enum基础types必须的广泛描述,所以每个编译器都会自己对经典enum的基本types进行enum ,有时结果可能会令人惊讶。 
例如,我曾经看过很多这样的代码:
 enum E_MY_FAVOURITE_FRUITS { E_APPLE = 0x01, E_WATERMELON = 0x02, E_COCONUT = 0x04, E_STRAWBERRY = 0x08, E_CHERRY = 0x10, E_PINEAPPLE = 0x20, E_BANANA = 0x40, E_MANGO = 0x80, E_MY_FAVOURITE_FRUITS_FORCE8 = 0xFF // 'Force' 8bits, how can you tell? }; 
 在上面的代码中,一些天真的编码器认为编译器会将E_MY_FAVOURITE_FRUITS值存储为一个无符号的8位types…但是没有任何保证:编译器可以selectunsigned char或int或short ,其中任何types都是大的足以适应在enum看到的所有值。 添加字段E_MY_FAVOURITE_FRUITS_FORCE8是一个负担,并且不会强制编译器对enum的基础types做出任何select。 
 如果有一些代码依赖于types大小和/或者假设E_MY_FAVOURITE_FRUITS会有一定的宽度(例如:序列化例程),那么这个代码可能会以一些奇怪的方式运行,这取决于编译器的想法。 
 而更糟糕的是,如果一些同事不小心增加了我们的enum的新价值: 
  E_DEVIL_FRUIT = 0x100, // New fruit, with value greater than 8bits 
 编译器不会抱怨! 它只是调整types以适应enum所有值(假定编译器使用的是可能的最小types,这是我们不能做的假设)。 这个简单和粗心的除了可以微妙的破解相关的代码。 
 因为C ++ 11可以指定enum和enum class的基础types(感谢rdb ),所以这个问题是整齐地解决: 
 enum class E_MY_FAVOURITE_FRUITS : unsigned char { E_APPLE = 0x01, E_WATERMELON = 0x02, E_COCONUT = 0x04, E_STRAWBERRY = 0x08, E_CHERRY = 0x10, E_PINEAPPLE = 0x20, E_BANANA = 0x40, E_MANGO = 0x80, E_DEVIL_FRUIT = 0x100, // Warning!: constant value truncated }; 
如果某个字段的expression式超出此types的范围,则指定基础types,编译器将会投诉,而不是更改基础types。
我认为这是一个很好的安全改进。
编辑
 那么为什么枚举类比普通枚举首选呢?  ,如果我们可以selectscoped( enum class )和unscoped( enum )枚举的基础types,还有什么使enum class更好的select? 
-  它们不会隐式转换为int。
- 他们不污染周围的名字空间。
- 他们可以被提前宣布。
使用枚举类超过正常枚举的基本优点是,你可能有两个不同的枚举相同的枚举variables,仍然可以解决它们(这已被提到OP types安全 )
例如:
 enum class Color1 { red, green, blue }; //this will compile enum class Color2 { red, green, blue }; enum Color1 { red, green, blue }; //this will not compile enum Color2 { red, green, blue }; 
 至于基本枚举,编译器将无法区分red是否指向Color1或Color2types,如下面的语句所示。 
 enum Color1 { red, green, blue }; enum Color2 { red, green, blue }; int x = red; //Compile time error(which red are you refering to??) 
枚举用于表示一组整数值。
  enum之后的class关键字指定枚举types是强types的,枚举types是作用域的。 这样, enum类可以防止意外滥用常量。 
例如:
 enum class Animal{Dog, Cat, Tiger}; enum class Pets{Dog, Parrot}; 
在这里,我们不能混合动物和宠物的价值观。
 Animal a = Dog; // Error: which DOG? Animal a = Pets::Dog // Pets::Dog is not an Animal