最近在看《A Tour of C++ 3rd》的时候发现 C 和 C++ 的 enum
虽然使用起来比较相似,但是目的却略有不同。关于枚举的概念还请见之前写过一篇关于 C 的那篇博客《C语言中enum(枚举)详解》,这里不再赘述。本文侧重 C++ 与 C 不同的地方。
首先,默认情况下与 C 一样,值的类型为整数,所以下面样式的代码依旧可以使用:
#include <iostream>enum {Jan=1, Feb, Mar, Apr, May, Jun, Jul, Aug, Sep, Oct, Nov, Dec};int main()
{int x1 = Jan;std::cout<<x1<<std::endl;
}
C++ 不同版本的枚举使用方法也有所不同,但是上面这种“plain”版本的都是一样的。所以本文不会详细介绍 C++11 到 C++23 每个版本的使用方法,主要是介绍概念(因为这个概念我花了一段时间才搞明白)。
但是《A Tour of C++ 3rd》和《The C Programming Language》这两本书对于枚举的目的描述却不太一样。
在《The C Programming Language》中,enum
被描述成一种“常量列表”;但是在《A Tour of C++ 3rd》中,enum
则被描述成一种用户定义类型的简单方式,相比 C 的enum
扩充了一些功能。
C++11 添加了作用域内枚举enum class
,有时候枚举可能会重名,这样就可以解决重名的问题了。如下:
enum class Color { red, blue, green };
enum class Light { red, blue, green };
要牢记enum class
是一个整体,含义是创建一个class
一样的枚举,也就是说class
后面的是一个自定义的类型,而大括号内的是这个“类”的域。
当我们要使用上面Color
中的red
时,需要按照表示red
所属的是哪个enum class
:
std::cout<<int(Color::red);
//OutPut:0
这里将Color
转换成基础数据类型,会发现也还是0
。但是需要注意,这里依旧和 C 中一样,Color::red
表示的是Color
的red, blue, green
三者中的red
这个常量,并不是类或结构体中的成员变量,这是非常容易混淆的一点。
如果使用了enum class
,虽然可以赋值、初始化、比较,但是就不能像 C 那样简单地输出这些枚举常量了,需要将其转换成基础数据类型(默认为整数)或者自己写输出功能。但是我们可以用enum class
创建的类型来创建新的常量:
Color x = Color::red;
std::cout<<int(x);
//OutPut:0
这里的x
会被认为和Color::red
是一类的,二者可以比较,如下:
if (x == Color::red) {std::cout<<"x等于Color::red";
}
//x等于Color::red
如果你看了我 C 的那一篇博客的话,最后提到枚举的一个用途就是对比(比如作为if
的判断部分)。所以 C++ 默认支持的三个功能之一就是比较。而且我们可以指定值来创建常量,方法如下(二者等价,但是不同版本 C++ 可能会不同):
Color x = Color(10); //C++11及更新版本
Color x {10}; //C++17及更新版本
这样x
就是和Color::red
是一个类型的常量,二者可以互相比较,但值为10
。这种方法虽然变得复杂了一些,但可以比较灵活地实现一些情况的判断。
书中给出了一个红绿灯的例子挺有意思的。(下面我修改了一些地方,不是书中的,但是思路一样)。
首先重载++x
操作符:
Color& operator++(Color& c)
{using enum Color; //这个要C++20switch (c) {case red: return c=blue;case blue: return c=green;case green: return c=red;}
}
然后就可以通过++x
获取到枚举列表的下一个元素:
Color x = Color::red;
std::cout<<int(x)<<std::endl;
std::cout<<int(++x)<<std::endl;
希望能帮到有需要的人~