枚举类型没有作用域,更喜欢枚举类而不是枚举?



我是c++的新手,我想知道是否有人可以帮助我理解为什么

enum difficulty { NOVICE, EASY, NORMAL, HARD, UNBEATABLE };
difficulty myDiffiuclty = EASY

enum shipCost { FIGHTER_COST = 25, BOMBER_COST, CRUISER_COST = 50 };
shipCost myShipCost = BOMBER_COST;

用绿色下划线?它说它更喜欢enum类,但当我把它改成enum类,然后

enum class difficulty { NOVICE, EASY, NORMAL, HARD, UNBEATABLE };
difficulty myDiffiuclty = EASY;
enum class shipCost { FIGHTER_COST = 25, BOMBER_COST, CRUISER_COST = 50 };
shipCost myShipCost = BOMBER_COST;

EASY变成红色下划线myShipCost用绿色下划线,BOMBER_COST用红色下划线,CRUISER_COST用红色下划线

const int ALIEN_POINTS = 150;
int aliensKilled = 10;
int score = aliensKilled * ALIEN_POINTS;
cout << "score: " << score << endl;
enum difficulty { NOVICE, EASY, NORMAL, HARD, UNBEATABLE };
difficulty myDifficulty = EASY;
enum shipCost { FIGHTER_COST = 25, BOMBER_COST, CRUISER_COST = 50 };
shipCost myShipCost = BOMBER_COST;
cout << "nTo upgrade my ship to a cruiser will cost "
<< (CRUISER_COST - myShipCost) << " Resource Points.n";
system("pause");
return 0;
enum class difficulty { NOVICE, EASY, NORMAL, HARD, UNBEATABLE };
difficulty myDiffiuclty = difficulty::EASY;
enum class shipCost { FIGHTER_COST = 25, BOMBER_COST, CRUISER_COST = 50 };
shipCost myShipCost = shipCost::BOMBER_COST;

enum class,隐式转换到/从整数,你必须限定其中的常量的作用域。

这被认为是一种改进。显式地将其转换回整数仍然有效,但这不是偶然发生的。

std::cout << "nTo upgrade my ship to a cruiser will cost "
<< (static_cast<int>(shipCost::CRUISER_COST) - static_cast<int>(myShipCost)) <<
" Resource Points.n";
system("pause");
return 0;

一旦你使用enum class,你应该重命名它们:

enum class difficulty { novice, easy, normal, hard, unbeatable };
difficulty myDiffiuclty = difficulty::easy;
enum class shipCost { fighter =25, bomber=30, cruiser = 50 };
shipCost myShipCost = shipCost::bomber;

作为名称的ship部分现在在enum中,不需要在常量中重复。同样,因为名称是有作用域的,所以您不必对它们进行SHOUT

但是,请注意,如果您只是使用它来创建常量而不打算创建类型,请考虑使用以下内容:
namespace ship {
namespace cost {
constexpr int fighter = 25;
constexpr int bomber = 30;
constexpr int cruiser = 50;
}
}

现在我们将ship::cost::fighter作为编译时计算的int,而不是enum class

现在您已经了解了上述答案的区别,我想指出"new"的几个地方。做事的方式坏了,你能做些什么。

考虑一下我遇到的这个(缩写的)实际例子,将我用C编写的一些音频软件移植到现代c++ (c++ 17):

typedef enum sample_type_e {
sample_type_uint16,
sample_type_double
}sample_type_t;

现在,首先要知道的是这里不再需要typedef;你可以在其他地方读到更多。继续…

此代码在Visual Studio 2019中编译,将导致您描述的错误。

现在,解决这个问题的一个方法将看起来像是移动到新的语法——但是看看会发生什么:

enum class SampleType {
uint16,
double
}

哦。

这行不通——double是保留字。现在,您可以恼怒地这样做:

enum class SampleType {
uint16,
type_double
}

…但这不是很一致,当你看到这个时:

enum class SampleType {
type_uint16,
type_double
}

…可以说,您已经达到了与这个新特性所声称的至少一个好处完全相反的效果:尽可能简洁,而不丢失上下文。

在我的假想但实际上是真实世界的例子中,麻烦的是你不能限定保留字的作用域:它们总是保留。(切线点:在某些语言中,这是不正确的…)

这就叫做"不走运"。它发生的频率比语言设计师愿意承认的要高得多,而且当你没有他们中的一个和你在一起的时候,它总是会出现。

所以,如果类似的事情碰巧出现在你面前,而你只是真的不喜欢尝试使用"class enum"最后看起来像,你会怎么做?

嗯,事实证明,您可以通过使用另一个语言特性来解决整个原始问题,该特性被认为是尽可能使用的良好实践:名称空间。如果我只对原始声明命名空间(减去粗糙的typedef),我得到:

namespace audiostuff {
enum sample_type_e {
sample_type_uint16,
sample_type_double
};
};

…只要使用这些东西的代码在相同的命名空间中,或者有

using namespace audiostuff;

放在最上面,或者,交替使用,像这样:

audiostuff::sample_type_e my_sample_type_var;

…然后,你瞧,Visual Studio停止了抱怨——其他编译器也应该停止抱怨。

毕竟,这个抱怨是在提醒您应该避免弄乱全局命名空间——尤其是在意外情况下。"类enum"是一种方法,但使用显式命名空间也是一种方法。

最新更新