强制枚举值不正确?

jCu*_*uga 6 c++ enums

我在C++的枚举中遇到了一些不寻常的(至少对我而言)行为.我在Visual Studio 2008和g ++版本4.4.3中尝试了以下内容

#include <iostream>
using namespace std;

enum testEnum
{
    // no zero enum
    one = 1,
    two = 2,
    three = 3
};

int main(int argc, char *argv[])
{
    testEnum e;  // undefined value (may be zero, but thats just luck)
    cout << "Uninitialized enum e = " << e << endl;

    /*
        testEnum e2(0);  // error converting from int to enum
    */

    testEnum e3(testEnum(0)); // forces zero !?!!?!?
    cout << "zero enum e3 = " << e3 << endl;  // prints '0'

    testEnum e4(testEnum(9999)); // forces 9999 ?!?!?!?!
    cout << "9999 enum e4 = " << e4 << endl; // prints '9999'

    return 0;
}
Run Code Online (Sandbox Code Playgroud)

e的未定义值是我所期望的,我理解为什么你不能从int转换为枚举(但你可以转向另一种方式).

我很好奇最后两个枚举(e3和e4)如何被允许编译并获得你想要给它们的任何值.

另外,我发现这个:

testEnum e();
Run Code Online (Sandbox Code Playgroud)

在studio和linux中编译,在linux中进行cout-ing产生'1',但在工作室中我遇到了一个链接器错误:

main.obj : error LNK2001: unresolved external symbol "enum testEnum __cdecl e2(void)"
Run Code Online (Sandbox Code Playgroud)

在工作室,我可以这样做:

testEnum e = testEnum();
Run Code Online (Sandbox Code Playgroud)

但是,它的结果是'0'而不是'1'

所以我的主要问题是如何在上面的例子中像e3和e4一样将任何值压缩到枚举的喉咙上.如果这取决于实现是否依赖.

Dav*_*nan 8

C++枚举不是类型安全的.正如你所说的那样,你可以将任何一个值压低到枚举喉咙.此功能不依赖于实现,它在标准中得到了体现.

C++ 11引入了强类型枚举,这些枚举使用不同的语法声明,以免破坏旧代码的类型不安全枚举.


Moo*_*uck 8

枚举保证在其最小定义值和最大定义值之间的范围内保持任何值,并且未指定它如何处理该范围之外的数字.

§7.2/ 3
...如果没有明确指定,则作用域枚举类型的基础类型是int."

§7.2/ 7
...对于枚举,其中emin是最小的枚举数且emax是最大的,枚举的值是bmin到bmax范围内的值,定义如下:令两个补码表示为K为1 0表示一个补码或符号幅度表示.bmax是大于或等于max(| emin | - K,| emax |)且等于2M-1的最小值,其中M是非负整数.如果emin是非负的,则bmin为零,否则为 - (bmax + K).如果bmin为零,则大小足以容纳枚举类型的所有值的最小位字段的大小为max(M,1),否则为M + 1.

§7.2/ 10
算术或枚举类型的表达式可以显式转换为枚举类型.如果它在枚举类型的枚举值范围内,则该值不变; 否则生成的枚举值未指定.

另请注意,testEnum e();声明一个返回a的函数.testEnum 这是由令人烦恼的解析引起的.不知道为什么GCC决定等于一个(也许它被强制转换为指针 - >某种方式的bool?) testEnum e = testEnum();是一个默认初始化a的有效语句testEnum,对于基元(显然enums)意味着将它们设置为零.

请注意,这并不意味着枚举可能不会超出其定义的范围; 如N4296脚注96所述:

这组值用于定义枚举类型的提升和转换语义.它不排除枚举类型的表达式具有超出此范围的值.

我还要提一下,在C++ 03中制作类型安全的枚举并不是特别复杂,只有一些奇怪的技巧. http://en.wikibooks.org/wiki/More_C%2B%2B_Idioms/Type_Safe_Enum显示了一种方式.