为什么我不能分配错误的枚举元素,但可以与错误的枚举元素进行比较?

时间:2011-07-06 06:43:27

标签: c++ enums types type-safety

使用以下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 ++中的处理方式不同?

4 个答案:

答案 0 :(得分:6)

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

答案 1 :(得分:4)

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

这种论证适用于unsigned intintsize_t等之间的比较,但可能由于同样的原因它们都限于编译器警告。

但是,使用enum class在C ++ 0x中解决了这个问题(它们没有更改现有的enum行为以保持兼容性。)

答案 2 :(得分:2)

它不是不可能的,它只是你的编译器认为它们只是整数时它们是两种不同的数据类型。因此,简单的类型转换可以解决问题。

EnumA variable;
variable = (EnumA)EB_Element;

答案 3 :(得分:1)

欢迎使用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不合逻辑的非推论)。但是字符是不合理的(不合逻辑的,但是C遗产)和双打可以隐含地转换为整数(不合逻辑,但C遗产)。因此,在C ++中,为字符串赋予双精度是不合逻辑的(但是合法的)。

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

对于你的问题,原因是enums在某些情况下就像是int(可能是因为用例的遗产),但在某些其他情况下却不像int。这是荒谬的,但它符合标准的要求。

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

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

挑选一本好书(或几本)并阅读(它们)封面以涵盖......遗憾的是没有别的办法。我的建议是:“C ++编程语言”(Stroustrup),“Effective C ++”&amp; “更有效的C ++”(Meyers),“C ++ FAQs”(Cline / Lomow / Girou)。

C ++是一个非常强大而且很好的武器,但它从错误的一面接近它,它可能成为你做恶梦的最糟糕的事情。假设你只能使用逻辑来理解它是一种错误的方法(并不是因为你的逻辑很弱,而是因为C ++不仅仅是逻辑)。