【问题标题】:Why can't I assign the wrong enum element, but can compare against the wrong enum element?为什么我不能分配错误的枚举元素,但可以与错误的枚举元素进行比较?
【发布时间】:2011-07-06 06:43:26
【问题描述】:

使用以下 C++ 定义:

enum EnumA {
    EA_Element = 1
};

enum EnumB {
    EB_Element = 10
};

以下代码无法编译,这只是有意义的:

EnumA variable;
variable = EB_Element; // won't compile

但以下代码确实可以编译:

EnumA variable = EA_Element;
if( variable == EB_Element ) { //will compile
}

虽然它没有任何意义 - 比较不同的枚举并且这样的代码可能是错误的。

为什么这些看似相同的情况在 C++ 中的处理方式不同?

【问题讨论】:

  • 不应该编译的情况是:variable = EB_Element;?

标签: c++ enums types type-safety


【解决方案1】:

它将编译,因为“默认情况下,枚举被转换为整数以进行算术运算。” (在:C++ 编程语言)

【讨论】:

    【解决方案2】:

    这个论点是正确的,因为我已经看到任何enum 类型都可以与任何enum 类型进行比较。这是因为出于比较目的,enum 变量和值应该转换为整数类型(例如int)。某些编译器会做raise the warning

    对于unsigned intintsize_t 等之间的比较,这样的论点可以成立,但可能出于同样的原因,它们都仅限于编译器警告。

    但是,这个问题在 C++0x 中通过 enum class 得到解决(他们没有更改现有的 enum 行为以保持兼容性)。

    【讨论】:

      【解决方案3】:

      这不是不可能,只是当它们都是整数时,编译器认为它们是两种不同的数据类型。所以一个简单的类型转换就可以解决这个问题。

      EnumA variable;
      variable = (EnumA)EB_Element;
      

      【讨论】:

        【解决方案4】:

        欢迎使用 C++!

        为了更有趣的东西试试这个:

        #include <string>
        
        int main(int argc, const char *argv[])
        {
            std::string s;
            s = 3.141592654;
            return 0;
        }
        

        为什么会编译?原因是语言规则是这样说的。

        在这个奇怪的情况下,关于为什么这个例子编译的“官方”解释是允许std::string::operator+=(char) (从实用的角度来看,IMO 可以和合乎逻辑)和“因此”也允许来自 char 的赋值(IMO 不合逻辑)似乎是正确的不合逻辑的推论)。但是 chars 是整数(不合逻辑,但 C 继承),双精度可以隐式转换为整数(不合逻辑,但 C 继承)。因此,在 C++ 中,将 double 分配给字符串是不合逻辑的(但合法)。

        如果您不知道,请不要难过,我展示的大多数 C++ 程序员都对为什么编译这样的废话感到困惑,并考虑其他语义或编译器错误。

        就您的问题而言,原因是枚举在某些情况下类似于整数(可能是因为用例的传统),但在其他情况下不像整数。这很荒谬,但这是标准要求的。

        如果您对这种明显缺乏逻辑感到不舒服,请记住 C++ 主要是悠久历史甚至是委员会(!)的结果,因此逻辑与它没有太大关系。这也意味着人们不能使用逻辑来避免学习 C++:无论你多么聪明,你都无法猜测历史事故和委员会的政治决定。

        C++ 的高度复杂性、许多地方缺乏逻辑以及存在undefined behavior daemons 而不是runtime error angels 也是IMO 基本上排除通过实验学习C++ 的原因。

        挑选一本(或几本)好书,从头到尾读一遍……不幸的是,别无他法。我的建议是:“C++ 编程语言”(Stroustrup)、“有效的 C++”和“更有效的 C++”(Meyers)、“C++ 常见问题解答”(Cline/Lomow/Girou)。

        C++ 是一个非常强大且不错的武器,但如果从错误的角度使用它,它可能会成为你最糟糕的噩梦。假设您仅使用逻辑就能理解它是一种错误的方法(并不是因为您的逻辑很弱,而是因为 C++ 不仅仅是逻辑)。

        【讨论】:

        • -1,您没有回答问题,示例与问题无关,逻辑与示例编译的原因有关。
        • 两种情况的答案都已经存在(因为标准是这样说的),我认为在理解 C++ 时警告高估逻辑能力的错误很重要。无论如何,如果这让您感觉更好,我已经添加了更详细的解释。我喜欢 C++,但如果你说它是一种逻辑语言,那么 IMO 你还处于狂热阶段。写了几十万行 C++ 代码后回来再说吧。
        • 哦,我写的 C++ 比我应得的要多,而且我不是一个狂热的粉丝。关于s=3.14159; 是的,这很丑。但是,从浮点到整数到字符到赋值的每一步都很好。您同意s += some_char; 可以。请注意,s+= some_char; 在空字符串的情况下与s = some_char; 具有相同的效果——因此提供operator=(char) 非常有意义。您的示例说明了组织为什么进行代码审查。仅仅因为一段代码是完全有效的,并不意味着它不会闻到天堂的味道。
        • 对不起,但我不同意如果你承认串联(务实的原因)那么你也必须承认分配。此外,我没有说其他段落是合乎逻辑的。它们确实是不合逻辑的,并且仅仅因为 C 传统而存在。就像size_t 未签名或默认调度是非虚拟的(即逻辑错误)一样,可能会有借口,但这些借口并不能使这些选择合乎逻辑。在使用 C++ 时,过多依赖逻辑而过少依赖实际 STUDY 会导致灾难。
        猜你喜欢
        • 1970-01-01
        • 2011-05-28
        • 1970-01-01
        • 1970-01-01
        • 2017-12-03
        • 1970-01-01
        • 2014-07-08
        • 1970-01-01
        • 2010-10-17
        相关资源
        最近更新 更多