237

假设我们有一个enum类似的内容:

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

我想创建一个实例enum并用适当的值初始化它,所以我这样做:

Days day = Days.Saturday;

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

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

这给了我一个编译错误:

错误:“。”之前的预期主表达式 令牌

所以要清楚,说之间有什么区别:

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

if (day == Saturday)

?

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

4

14 回答 14

380

这段代码是错误的:

enum Days {Saturday, Sunday, Tuesday, Wednesday, Thursday, Friday};
Days day = Days.Saturday;
if (day == Days.Saturday)

因为Days不是范围,也不是对象。它是一种类型。并且类型本身没有成员。你写的相当于std::string.clear. std::string是一种类型,所以你不能.在它上面使用。您.在类的实例上使用。

不幸的是,枚举是神奇的,所以类比到此为止。因为有了一个类,你可以做得到std::string::clear一个指向成员函数的指针,但是在C++03中,Days::Sunday是无效的。(这是可悲的)。这是因为 C++(在某种程度上)与 C 向后兼容,并且 C 没有命名空间,因此枚举必须在全局命名空间中。所以语法很简单:

enum Days {Saturday, Sunday, Tuesday, Wednesday, Thursday, Friday};
Days day = Saturday;
if (day == Saturday)

幸运的是,Mike Seymour发现这已在 C++11 中得到解决。更改enumenum class并获得自己的范围;soDays::Sunday不仅有效,而且访问Sunday. 快乐的时光!

于 2012-08-29T17:26:52.940 回答
26

这足以声明您的枚举变量并进行比较:

enum Days {Saturday, Sunday, Tuesday, Wednesday, Thursday, Friday};
Days day = Saturday;
if (day == Saturday) {
    std::cout << "Ok its Saturday";
}
于 2012-08-29T17:04:03.990 回答
24

其中大部分应该会给你编译错误。

// 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)
    // ...

这些enum值就像裸常量——它们没有作用域——在编译器的一些额外帮助下:(除非你使用 C++11枚举类)它们不像对象或结构成员那样封装,并且您不能将它们称为.Days

您将拥有您正在寻找的C++11,它引入了一个enum class

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

// ...

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

请注意,此 C++ 在几个方面与 C 略有不同,一个是 Cenum在声明变量时需要使用关键字:

// day declaration in C:
enum Days day = Saturday;
于 2012-08-29T17:07:11.807 回答
18

您可以根据需要使用技巧来使用范围,只需以这种方式声明枚举:

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

Days::type day = Days::Saturday;
if (day == Days::Saturday)
于 2014-09-11T11:39:06.043 回答
12

枚举不是使用一堆 if 语句,而是很适合切换语句

我在为我的游戏构建的关卡构建器中使用了一些枚举/开关组合。

编辑:另一件事,我看到你想要类似于的语法;

if(day == Days.Saturday)
etc

您可以在 C++ 中执行此操作:

if(day == Days::Saturday)
etc

这是一个非常简单的例子:

EnumAppState.h

#ifndef ENUMAPPSTATE_H
#define ENUMAPPSTATE_H
enum eAppState
{
    STARTUP,
    EDIT,
    ZONECREATION,
    SHUTDOWN,
    NOCHANGE
};
#endif

一些文件.cpp

#include "EnumAppState.h"
eAppState state = eAppState::STARTUP;
switch(state)
{
case STARTUP:
    //Do stuff
    break;
case EDIT:
    //Do stuff
    break;
case ZONECREATION:
    //Do stuff
    break;
case SHUTDOWN:
    //Do stuff
    break;
case NOCHANGE:
    //Do stuff
    break;
}
于 2012-08-29T17:10:53.790 回答
10

您正在寻找强类型枚举,这是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++ 标准。

如果您使用的是 GCC,请使用-std=c++11-std=gnu11启用 C+11 。

要开心!

于 2016-08-13T14:00:20.680 回答
9

如果您仍在使用 C++03 并想使用枚举,则应该在命名空间内使用枚举。例如:

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

您可以在命名空间之外使用枚举,例如,

Daysofweek::Days day = Daysofweek::Saturday;

if (day == Daysofweek::Saturday)
{
    std::cout<<"Ok its Saturday";
}
于 2017-05-04T18:57:38.340 回答
7

这在 C++ 中不应该工作:

Days.Saturday

Days 不是包含可以使用点运算符访问的成员的范围或对象。这种语法只是 C# 主义,在 C++ 中是不合法的。

Microsoft 长期以来一直维护一个 C++ 扩展,允许您使用范围运算符访问标识符:

enum E { A, B, C };

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

但这在 C++11 之前是非标准的。在 C++03 中,枚举中声明的标识符仅存在于与枚举类型本身相同的范围内。

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

C++11 使得用枚举名称限定枚举标识符是合法的,并且还引入了枚举类,它为标识符创建一个新的范围,而不是将它们放在周围的范围中。

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

enum class F { A, B, C };

A; // error
F::B;
于 2012-08-29T17:18:14.773 回答
5

可悲的是,枚举的元素是“全球性的”。您可以通过执行来访问它们day = Saturday。这意味着你不能拥有enum A { a, b } ;enum B { b, a } ;因为它们是冲突的。

于 2012-08-29T17:10:04.103 回答
4

虽然 C++(不包括 C++11)有枚举,但它们中的值被“泄露”到全局命名空间中。
如果您不想让它们泄露(并且不需要使用枚举类型),请考虑以下事项:

class EnumName {  
   public:   
      static int EnumVal1;  
      (more definitions)  
};  
EnumName::EnumVal1 = {value};  
if ([your value] == EnumName::EnumVal1)  ...
于 2016-04-11T01:43:56.247 回答
3

当你声明你的枚举值时,C++ 中的枚举就像被你给它们的名字所掩盖的整数(这不是一个定义,只是一个提示它是如何工作的)。

但是您的代码中有两个错误:

  1. 拼写enum全部小写
  2. 你不需要Days.星期六之前的。
  3. 如果此枚举在类中声明,则使用 if (day == YourClass::Saturday){}
于 2012-08-29T17:09:05.083 回答
1

我认为您的根本问题是使用 of.而不是::,它将使用命名空间。

尝试:

enum Days {Saturday, Sunday, Tuesday, Wednesday, Thursday, Friday};
Days day = Days::Saturday;
if(Days::Saturday == day)  // I like literals before variables :)
{
    std::cout<<"Ok its Saturday";
}
于 2015-06-06T19:30:37.823 回答
1

如果我们想要严格的类型安全和范围枚举,那么enum class在 C++11 中使用是很好的。

如果我们必须在 C++98 中工作,我们可以使用 , 给出的建议InitializeSahibSan启用作用域枚举。

如果我们还想要严格的类型安全,下面的代码可以实现类似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 类示例

于 2020-04-18T09:41:37.743 回答
-15

首先,使枚举中的'E','e'小写。

其次,在“Days.Saturday”中删除类型名称“Days”。

第三……给自己买一本好的 C++ 书。

于 2012-08-29T17:11:22.850 回答