我听到一些人建议在c++中使用枚举类,因为它们的类型安全。

但这到底是什么意思呢?


当前回答

与普通枚举相比,使用枚举类的基本优点是您可以为两个不同的枚举使用相同的枚举变量,并且仍然可以解析它们(这已经被OP提到为类型安全)。

如:

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 };

对于基本枚举,编译器将无法区分红色是指下面语句中的类型Color1还是Color2。

enum Color1 { red, green, blue };   
enum Color2 { red, green, blue };
int x = red;    //Compile time error(which red are you refering to??)

其他回答

因为,正如在其他答案中所说,类enum不能隐式转换为int/bool,这也有助于避免有bug的代码,如:

enum MyEnum {
  Value1,
  Value2,
};
...
if (var == Value1 || Value2) // Should be "var == Value2" no error/warning

还有一件事没有明确提到——作用域特性提供了一个选项,可以让枚举和类方法具有相同的名称。例如:

class Test
{
public:
   // these call ProcessCommand() internally
   void TakeSnapshot();
   void RestoreSnapshot();
private:
   enum class Command // wouldn't be possible without 'class'
   {
        TakeSnapshot,
        RestoreSnapshot
   };
   void ProcessCommand(Command cmd); // signal the other thread or whatever
};

c++有两种类型的enum:

枚举类 简单的枚举

下面是几个关于如何声明它们的例子:

 enum class Color { red, green, blue }; // enum class
 enum Animal { dog, cat, bird, human }; // plain enum 

这两者之间有什么区别?

枚举类——枚举器名称是枚举的本地名称,它们的值不会隐式转换为其他类型(比如另一个枚举或int)。 普通枚举——枚举器名称与枚举及其所在的枚举在同一作用域内 值隐式地转换为整数和其他类型

例子:

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;

}

结论:

枚举类应该是首选的,因为它们较少引起可能导致错误的意外。

值得注意的是,在这些答案之上,c++ 20解决了枚举类的一个问题:冗长。想象一个假设的枚举类Color。

void foo(Color c)
  switch (c) {
    case Color::Red: ...;
    case Color::Green: ...;
    case Color::Blue: ...;
    // etc
  }
}

与普通枚举变体相比,这是详细的,其中名称在全局作用域中,因此不需要用Color::作为前缀。

然而,在c++ 20中,我们可以使用using enum将枚举中的所有名称引入到当前作用域,从而解决了这个问题。

void foo(Color c)
  using enum Color;
  switch (c) {
    case Red: ...;
    case Green: ...;
    case Blue: ...;
    // etc
  }
}

所以现在,没有理由不使用枚举类。

与普通枚举相比,使用枚举类的基本优点是您可以为两个不同的枚举使用相同的枚举变量,并且仍然可以解析它们(这已经被OP提到为类型安全)。

如:

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 };

对于基本枚举,编译器将无法区分红色是指下面语句中的类型Color1还是Color2。

enum Color1 { red, green, blue };   
enum Color2 { red, green, blue };
int x = red;    //Compile time error(which red are you refering to??)