C++枚举

1. 概述

本篇主要讲的是C++的枚举,ENUM是enumeration的缩写。基本上,它就是一个数值集合,如果你想要给枚举一个更实际的定义,他们是给一个值命名的一种方法,所以我们不用一堆叫做a,b,c的整数,我们可以有一个枚举数,它的值是a,b,c,与证书对应。它还能帮助我们,将一组数值集合作为类型,而不仅仅是用整型作为类型。当然,我们可以给它赋值任何整数,或者限制哪些值可以赋值。这一点都不复杂,就是这样,它只是一种命名值的方法,当我们想要使用整数来表示某些状态或者某些数值时,枚举将非常有用。然而,我们希望为它们指定一个名称,以便代码更容易阅读。不管怎么说,枚举数其实就是一个整数,然而,在我们的代码中,看起来有点不一样,它还能让我们的代码保持干净。

2. 案例

1. 项目准备

准备一个简单的项目,项目中有一个main.cpp文件,内容如下

2. 开始案例

假设我们有三个值想要处理,如下,A,B,C

现在我们有三个值A,B,C,然后在main函数的某个地方,我们可能会使用我们的value变量,让它等于这三个中的一个。

我们可能有一些代码来检查当前的value值是什么,然后执行某种操作。如下

然而,这带来了一些问题

首先,这些A,B,C根本没有分组,在代码后面的某个地方,我们可能会有一个D,或者我们可能想再次声明A

那这就成了一个问题。但本质上最大的问题是这些根本没有分组。

此外,它们是整数,也就是说,我们可以直接让value等于5

那下面的判断,就没有任何意义了。

我们希望能够本质上定义一个类型,只能是这三个数中的一种,而且能够把他们组合起来,这正是我们可以使用枚举的地方。

我们改变做法,我们创建一个枚举ENUM,假设叫Example,然后列出我们想要的值

这里不用int作为类型了,我们现在可以使用枚举的名称作为实际类型。

然后,我们将定义的整型变量A,B,C改成小写

这样,我们就能正确的使用我们的枚举了。

可以看到,我们可以像这样赋值Example value = B;

如果我们想赋值其他的值如Example value = 5;

可以看到,我们会得到一个错误,因为它必须是ExampleA, B, C这三个中的一个。记住一点,不管怎么说,这里面的数值只能是整数。

如果,我们继续将value值赋值为B

然后进行检查,例如value == 1

因为这个值确实是1,如果我们把鼠标悬停在Example的B值上

VS会告诉我们B值是1,我们也可以指定这些变量的值。枚举中,默认第一个的值是0,后面的一个接一个递增

如果我们指定第一个数是某个值,比如设为0,B设为2,C设为6,我们想设为什么都行。

如果我们从一个非0的数字开始,比如A设为5,然后我们没有指定其他的值

我们鼠标悬停在B上

可以看到B的值是6。

C的值是7。这是因为它从5开始,然后递增。

我们还可以做一件事,指定我们想要给枚举赋值的整数类型,我们可以在Example后面跟冒号然后写数据类型

枚举默认是32位整型,然而,在这个例子中,我们没有必要使用32位。我们可以使用8位整型,比如unsigned char。就可以了,只是减少了内存使用。

我们不能使用float,因为float不是整数。

它必须是一个整数,所以我们可以放char

这就是枚举的本质,它只是给特定的值命名的一种方式,这样我们就不必在各种地方,处理各种整数

使用枚举改进日志类

下面,让我们来看看一个真正的例子,我们可能用到枚举。通过我们的日志类,这个Log类在如何写一个C++类那章讲过。内容如下

我们看到log类,使用了三个不同的log级别

而这三个log级别只是整数0、1、2。所以,这里是一个非常适合用枚举的地方。因为有三个值,我们用它们作为整数来表示某个状态。在这个例子中,日志级别的意思是指会展示哪种级别的日志。所以,在这个log类中,我们要创建一个名为Level的枚举,并将Error, Wraning, Info作为可能值。

就风格而言,我更喜欢显示的写成Error = 0,然而,这不是必须的,因为默认情况下它是从0开始的。这只是一些我喜欢做的事,以帮助代码更有可读性。

然后我们就可以删掉那些const 日志级别了

现在的日志级别中,int现在不作为我的log级别的类型了

但也可以保留它,我仍然可以将它赋值为Info

因为枚举其实是整数,这样做还是可以的,然而,在这种情况下,我可以将任何值设置为日志级别,将任何数值设置为日志级别,但我想让日志级别限制在这三个数值里面的话,我们还是应当将当前日志级别类型设置为level

注意我创建的这个限制条件,它就必须是Error, Warning, Info这三个了。

纯粹从语法上,C++编译器会强制执行这些限制,但我们也可以很容易的绕过它。它不是那种从物理上都无法设定的东西。当然,在这种情况下,我们的枚举数只是4个字节的整数。它只有4个字节的内存,我们可以把任何我们想要的东西,放进那个内存里。然而,通过设置类型为枚举Level,来限制我们的代码,只允许Level枚举数。

下面来改动其他地方,设置日志级别时,接收Level枚举数

日志打印,if判断,因为m_LogLevel是枚举类型,也就是它是一个整数,我们仍然可以比较它们。

这里改变的另一件事是,log.SetLevel(),这里的log.LogLevelError

现在它只是变成了Log::Error

因为我们有一个枚举数叫做Error,在log这个类的命名空间中。

注意这个枚举Level本身不是一个命名空间,这叫做枚举类。然而对于普通的枚举而言,这个Level并不是真正的命名空间,所以我们不能把它当做一个命名空间,这意味着这个Error, Warning, Info只存在于这个日志类中。

你可能已经注意到,log.SetLevel(Log::Error);实际上并不起作用,之所以会这样是因为我们还有一个叫做Error的函数,相同的名字

我特意设置这个,是为了告诉你们,如果名字冲突会发生什么。在这个例子中,这是行不通的,因为当我们尝试引用像Error这样的东西时,它不知道指的是函数还是枚举中的枚举值。所以我们应该将他们区分开。如加个前缀。

这是很常见的做法,这样我们就知道我们指的是什么。

注释掉main.cpp中的main函数

F5运行我们的程序

可以看到,得到了我们期望的结果。之所以Error被打印,是因为我们将日志级别设定为Error。

好了,枚举的本质上只是让我们的生活更加容易,让我们的代码更干净。在枚举的后面,其实就是整数。我们可以把它们用在很多地方,比如整数,枚举有很多很多的用途。本质上,如果我们有一个数值集合,而我们想用数字来表示它,枚举就是我们想要的。

相关推荐
蜉蝣之翼❉4 小时前
CRT 不同会导致 fopen 地址不同
c++·mfc
aramae4 小时前
C++ -- STL -- vector
开发语言·c++·笔记·后端·visual studio
lixzest4 小时前
C++ Lambda 表达式详解
服务器·开发语言·c++·算法
_Chipen5 小时前
C++基础问题
开发语言·c++
灿烂阳光g5 小时前
OpenGL 2. 着色器
c++·opengl
AA陈超7 小时前
虚幻引擎UE5专用服务器游戏开发-20 添加基础能力类与连招能力
c++·游戏·ue5·游戏引擎·虚幻
mit6.8247 小时前
[Meetily后端框架] AI摘要结构化 | `SummaryResponse`模型 | Pydantic库 | vs marshmallow库
c++·人工智能·后端
R-G-B7 小时前
【02】MFC入门到精通——MFC 手动添加创建新的对话框模板
c++·mfc·mfc 手动添加创建新的对话框
linux kernel7 小时前
第七讲:C++中的string类
开发语言·c++
Tipriest_8 小时前
[数据结构与算法] 优先队列 | 最小堆 C++
c++·优先队列·数据结构与算法·最小堆