提问者:小点点

枚举类型是不确定的,更喜欢枚举类而不是枚举?


我是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;

共2个答案

匿名用户

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;

使用<code>enum类</code>,将删除对整数的隐式转换,并且必须限定其中的常量范围。

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

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 difficulty { novice, easy, normal, hard, unbeatable };
difficulty myDiffiuclty = difficulty::easy;

enum class shipCost { fighter =25, bomber=30, cruiser = 50 };
shipCost myShipCost = shipCost::bomber;

因为名称的< code>ship部分现在在< code>enum中,所以不需要在常数中重复它。类似地,因为名称是有作用域的,所以您不必< code >喊它们。

但是,请注意,如果您只是使用它来创建常量,而无意创建类型,请考虑使用以下内容:

namespace ship {
  namespace cost {
    constexpr int fighter = 25;
    constexpr int bomber = 30;
    constexpr int cruiser = 50;
  }
}

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

匿名用户

既然你了解了其中的区别,从上面的答案中,我想指出一些“新的”做事方式失败的地方,以及你可以做些什么。

考虑一下我遇到的这个(缩写)实际示例,将我用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
}

糟糕。

这是行不通的——双精度是一个保留的词。现在,你可以愤怒地这样做:

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停止了抱怨——其他编译器也应该停止抱怨。

毕竟,抱怨是为了提醒你,你应该避免把全局命名空间弄得一团糟——尤其是因为意外。“类枚举”是实现这一点的一种方法,但使用显式名称空间也是如此。