19 February 2016
版权声明:本文基于署名 2.5 中国大陆许可协议发布,欢迎转载,演绎或用于商业目的,但是必须保留本文的署名elloop(包含链接)

#前言

本文总结了C++中的枚举类型enum在编程中的运用。从C++11开始,enum分为两种:

  • Unscoped Enum: “旧式”Enum,在C++11之前直接使用enum关键字定义的枚举

  • Scoped Enum: C++11开始引入的强类型枚举,使用关键字enum class或者enum struct定义的枚举

本文针对Unscoped Enum的使用来总结,不会涉及基本的语法细节。

基本用法小技巧

1. enum元素的个数

在实际开发中经常需要知道一个enum中有多少个元素,可以通过在enum最后加上一个名为Count的枚举,它就是enum元素的个数。

示例代码如下:

// 枚举元素的命名风格采用了Google C++风格
enum Color
{
    kRed,
    kGreen,
    kBlue,
    kYellow,
    kPink,
    kPurple,
    kColorCount,
};

RUN_GTEST(EnumClassTest, Unscoped, @);

// 定义并初始化一个枚举数组,每个分量取值enum中不同的值
Color colors[kColorCount];

for (int i=0; i<kColorCount; ++i) 
{
    colors[i] = static_cast<Color>(i);
}

// 检查colors中每个枚举的取值是否是Color中对应元素的值
for (int i=0; i<kColorCount; ++i) 
{
    Color color_i = static_cast<Color>(kRed + i);
    assert(colors[i] == color_i);
}

END_TEST;

理论基础是:Unscoped Enum的基本类型是int,且默认第一个元素的初值是0,某个枚举元素E(n)的值如果不显式指定,那么E(n)的值就等于E(n-1) + 1.

the enum hack

enum hack是旧式枚举的经典用法,它是把枚举元素用做一个编译时整型常量来用,在C++ TMP中特别常用。

这个概念我最早是在Effective C++中见到(Item2):

旧式枚举的经典用法,

class GamePlayer
{
private:
    enum { NumTurns = 5};

    int scores[NumTurns];       // NumTurns被当做一个编译时常量使用

}

the enum hack 用到了C++中的一个语法规则:enum的成员可以隐式转换为int.

enum类型转换

1. enum与int转换

从上面两段代码中可以看到,

  • enum转int是自动的。可以看到上面在定义数组时,直接使用枚举元素作为数组的长度。

  • int转enum需要显示类型转换。第一段代码中在给colors[i]赋值的时候,使用了static_cast<Color>的静态类型转换操作符。

enum 算数运算

enum类型的变量和int进行运算,运算结果是什么类型呢?

RUN_GTEST(EnumClassTest, Arithmetic, @);

Color red = kRed;
psln(typeid(red).name());   // 打印red的类型名称

int i = 1;
bool same = std::is_same<decltype(i), decltype(i + red)>::value;    // 假定i和red运算的结果类型和i的类型一致
EXPECT_TRUE(same);

END_TEST;

输出:

[ RUN      ] EnumClassTest.Arithmetic
@@@@@@@@@@ EnumClassTest ---> Arithmetic @@@@@@@@@@
typeid(red).name() = enum elloop::enum_class::Color
[       OK ] EnumClassTest.Arithmetic (3 ms)

从测试结果可以看到:

  • red的类型名叫enum_class::Color, 前面的elloop是我自定义的命名空间;

  • EXPECT_TRUE(same)的测试通过,这意味着enum和int运算的结果类型是int类型。

如果把i的类型改为long类型,那么测试依然能够通过。enum的类型会被提升为与i一样的类型,有点像内置数据类型的算数运算法则:“低精度的会转为较高精度的类型然后参与运算,结果也是较高精度的类型”

源码及参考链接


作者水平有限,对相关知识的理解和总结难免有错误,还望给予指正,非常感谢!

在这里也能看到这篇文章:github博客, CSDN博客, 欢迎访问



分享到