Wang's blog

枚举

Published on

无作用域枚举(enum)

C++11之前存在的枚举为无作用域枚举,使用enum关键字声明:

enum Color
{
    red,
    green,
    blue
};

每个枚举项都成为该枚举类型的一个具名常量,在它的外围作用域可见,且可以用于要求常量的任何位置:

Color r = red;

每个枚举类型都有一个底层类型,可以显式指定底层类型:

enum smallenum : std::int16_t
{
    a,
    b,
    c
};

可以在枚举项列表中提供初始化器,各枚举项的值由那些初始化器所定义。如果首个枚举项无初始化器,那么它的关联值为零。对于其他任何定义中无初始化器的枚举项,它的关联值是前一枚举项加一:

enum Foo
{
    a,
    b,
    c = 10,
    d,
    e = 1,
    f,
    g = f + c
};

无作用域枚举类型的值可隐式转换到整型类型:

int n = blue;

无作用域枚举的名字可以忽略:

enum
{
    a,
    b,
    c = 0,
    d = a + 2
};

使用无作用域枚举可能产生以下问题:

  • 由于枚举项在任何作用域可见,因此容易与其它变量名称产生冲突
  • 由于枚举项可隐式转换到整型类型,因此有时会发生未预期的转换

有作用域枚举(enum class或enum struct)

C++11引入新的有作用域枚举,使用enum class或enum struct关键字声明:

enum class Color
{
    red,
    green,
    blue
};

每个枚举项都成为该枚举类型的具名常量,它被该枚举的作用域所包含,必须用作用域解析运算符访问:

Color r = Color::blue;

没有从有作用域枚举项到整数类型的隐式转换,必须使用static_cast获得枚举项的数值:

int n = static_cast<int>(r);

有作用域枚举的其它操作与无作用域枚举基本相同。可以看出,有作用域枚举避免了无作用域枚举容易引发的问题。