假设我们有一个枚举,如下所示:

enum Days {Saturday, Sunday, Tuesday, Wednesday, Thursday, Friday};

我想创建这个枚举的一个实例,并初始化它与一个适当的值,所以我做:

Days day = Days.Saturday;

现在我想用一个现有的enum值检查我的变量或实例,所以我这样做:

if (day == Days.Saturday)
{
    std::cout << "Ok its Saturday";
}

这给了我一个编译错误:

错误:在`之前期望主表达式。“令牌

所以要明确的是,这两者的区别是什么

if (day == Days.Saturday) // Causes compilation error

and

if (day == Saturday)

?

这两个实际上指的是什么,一个是OK,一个导致编译错误?


当前回答

这其中大部分应该会给您带来编译错误。

// note the lower case enum keyword
enum Days { Saturday, Sunday, Monday, Tuesday, Wednesday, Thursday, Friday };

现在,Saturday, Sunday等可以用作顶级裸常量,Days可以用作类型:

Days day = Saturday;   // Days.Saturday is an error

类似地,后来,为了测试:

if (day == Saturday)
    // ...

这些枚举值就像纯粹的常量——它们是无作用域的——在编译器的一点额外帮助下(除非你使用c++ 11枚举类):它们不像对象或结构成员那样被封装,并且你不能将它们引用为Days的成员。

你会得到你想要的c++ 11,它引入了一个枚举类:

enum class Days
{
    SUNDAY,
    MONDAY,
    // ... etc.
}

// ...

if (day == Days::SUNDAY)
    // ...

注意,这个c++在一些方面与C略有不同,一个是C在声明变量时要求使用enum关键字:

// day declaration in C:
enum Days day = Saturday;

其他回答

如果我们想要严格的类型安全和有作用域的enum,在c++ 11中使用enum类是很好的。

如果我们必须在c++ 98中工作,我们可以使用InitializeSahib,San给出的建议来启用作用域enum。

如果我们还想要严格的类型安全,下面的代码可以实现类似enum的东西。

#include <iostream>
class Color
{
public:
    static Color RED()
    {
        return Color(0);
    }
    static Color BLUE()
    {
        return Color(1);
    }
    bool operator==(const Color &rhs) const
    {
        return this->value == rhs.value;
    }
    bool operator!=(const Color &rhs) const
    {
        return !(*this == rhs);
    }

private:
    explicit Color(int value_) : value(value_) {}
    int value;
};

int main()
{
    Color color = Color::RED();
    if (color == Color::RED())
    {
        std::cout << "red" << std::endl;
    }
    return 0;
}

代码修改自《Effective c++ 3rd: Item 18》一书中的Month类示例

这其中大部分应该会给您带来编译错误。

// note the lower case enum keyword
enum Days { Saturday, Sunday, Monday, Tuesday, Wednesday, Thursday, Friday };

现在,Saturday, Sunday等可以用作顶级裸常量,Days可以用作类型:

Days day = Saturday;   // Days.Saturday is an error

类似地,后来,为了测试:

if (day == Saturday)
    // ...

这些枚举值就像纯粹的常量——它们是无作用域的——在编译器的一点额外帮助下(除非你使用c++ 11枚举类):它们不像对象或结构成员那样被封装,并且你不能将它们引用为Days的成员。

你会得到你想要的c++ 11,它引入了一个枚举类:

enum class Days
{
    SUNDAY,
    MONDAY,
    // ... etc.
}

// ...

if (day == Days::SUNDAY)
    // ...

注意,这个c++在一些方面与C略有不同,一个是C在声明变量时要求使用enum关键字:

// day declaration in C:
enum Days day = Saturday;

您正在寻找强类型枚举,这是c++ 11标准中提供的一个特性。它将枚举转换为具有作用域值的类。

使用您自己的代码示例,它是:

  enum class Days {Saturday, Sunday, Tuesday,Wednesday, Thursday, Friday};
  Days day = Days::Saturday;

  if (day == Days::Saturday)  {
    cout << " Today is Saturday !" << endl;
  }
  //int day2 = Days::Sunday; // Error! invalid

如果目标是c++ 11之前的c++标准,则使用::作为枚举的访问器将失败。但一些旧的编译器不支持它,以及一些ide只是覆盖这个选项,并设置一个旧的c++ std。

如果您正在使用GCC,请使用-std=c++11或-std=gnu11启用C+11。

这在c++中是行不通的:

Days.Saturday

Days不是包含可以用点操作符访问的成员的作用域或对象。这种语法只是c#主义,在c++中是不合法的。

微软长期以来维护了一个c++扩展,允许您使用作用域操作符访问标识符:

enum E { A, B, C };

A;
E::B; // works with Microsoft's extension

但这在c++ 11之前是不标准的。在c++ 03中,在enum中声明的标识符只存在于与enum类型本身相同的范围内。

A;
E::B; // error in C++03

c++ 11允许用enum名称限定enum标识符,并且还引入了enum类,这些类为标识符创建了一个新的作用域,而不是将它们放在周围的作用域中。

A;
E::B; // legal in C++11

enum class F { A, B, C };

A; // error
F::B;

不要把enum看成一组对象,把它看成一个整数,其中每个数值都有一个名称,所以enum Days最好声明为enum Day。 如果你想把它包含在一个命名结构中,把enum Day放在一个结构Days中,就像这样:

struct Days{
    enum Day{
        Saturday,
        Sunday,
        Tuesday,
        Wednesday,
        Thursday,
        Friday
    };
};

然后您可以像这样称呼它们Days::Saturday,类型为Days::Day