如何在c++中使用枚举

假设我们有一个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)

?

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

490571 次浏览

这将足以声明你的enum变量并进行比较:

enum Days {Saturday, Sunday, Tuesday, Wednesday, Thursday, Friday};
Days day = Saturday;
if (day == Saturday) {
std::cout << "Ok its Saturday";
}

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

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

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

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

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

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

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

你将得到你想要的c++ 11,它引入了enum class:

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


// ...


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

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

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

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

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

  1. 拼写enum全部小写
  2. 在星期六之前你不需要Days.
  3. 如果这个enum是在类中声明的,那么使用 李if (day == YourClass::Saturday){} < / >

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

比起使用一堆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

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

首先,让“E”在enum中,“E”为小写。

其次,在“Days. saturday”中输入名称“Days”。

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

这在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 Days {Saturday, Sunday, Tuesday, Wednesday, Thursday, Friday};
Days day = Days.Saturday;
if (day == Days.Saturday)

因为Days既不是作用域,也不是对象。它是一种类型。类型本身没有成员。你所写的等价于std::string.clearstd::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)

幸运的是,迈克·西摩注意到这个问题在c++ 11中已经解决了。将enum更改为enum class,它将获得自己的作用域;所以Days::Sunday不仅有效,而且是访问Sunday只有方式。快乐的日子!

你可以使用一个技巧来使用你想要的作用域,只需像这样声明enum:

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


Days::type day = Days::Saturday;
if (day == Days::Saturday)

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

试一试:

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";
}
虽然c++(不包括c++ 11)有枚举,但枚举中的值会被“泄漏”到全局命名空间 如果你不想让它们泄露(并且不需要使用枚举类型),考虑以下:

class EnumName {
public:
static int EnumVal1;
(more definitions)
};
EnumName::EnumVal1 = {value};
if ([your value] == EnumName::EnumVal1)  ...

你正在寻找强类型枚举,一个在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,请使用化c++ 11化gnu11启用C+11。

如果你仍然在使用c++ 03并且想要使用枚举,你应该在命名空间中使用枚举。 如:< / p >
namespace Daysofweek{
enum Days {Saturday, Sunday, Tuesday,Wednesday, Thursday, Friday};
}

你可以像这样在命名空间之外使用枚举,

Daysofweek::Days day = Daysofweek::Saturday;


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

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

如果我们必须在c++ 98中工作,我们可以使用InitializeSahibSan给出的建议来启用作用域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类示例

不要把枚举看作一组对象,而是把它看作一个整数,其中每个数值都有一个名称,因此enum Days最好声明为enum Day。 如果你想在命名结构中包含它,将enum Day放在struct Days中,如下所示:

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

然后你可以这样寻址它们Days::Saturday,类型将是Days::Day