我是 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 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
。
现在您已经从上面的答案中了解了其中的区别,我想指出一些“新”做事方式出现问题的地方,以及您可以采取哪些措施。
考虑一下我遇到的这个(缩写的)实际示例,将我用 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
}
...可以说,您已经实现了与这一新功能所声称的至少一个好处完全相反的效果:尽可能简洁,而又不丢失上下文。我的假设是人为的但实际上是现实世界的示例中的麻烦在于,您无法确定保留字的范围:它们
总是保留。 (切线兴趣点:有些语言从来都不是这样的......)
这叫“倒霉”;这种情况发生的频率比语言设计者愿意承认的要高得多,而且当你身边没有他们之一时,它总是会出现。所以,如果类似的事情发生在你身上,而你
真的不喜欢尝试使用“类枚举”的结果,你会做什么?
好吧,事实证明,您可以通过使用另一个语言功能来解决整个原始问题,该功能被认为是尽可能使用的良好实践:命名空间。如果我只是命名原始声明(减去粗糙的 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 不再抱怨了——其他编译器也应该如此。毕竟,这个抱怨是为了提醒您应该避免弄乱全局名称空间——尤其是意外情况下。 “类枚举”是一种方法,但使用显式命名空间也是如此。
我认为 C++ 标准的更改没有任何意义。