今天我们简单补充一个有关于枚举类型ENUM的知识。
枚举(enumerate)本质上是一种命名值的方法,是某些值的集合,它专门处理某些变量只能选取某些特定的值的情况。比如说我们有一个标注状态的变量flag,而这个flag只能取值为0或者1,我们当然可以直接写这样一个变量出来,但是这也就意味着flag还可以取其他的值,这回给我们的代码带来一定的风险,因为我们只想这个flag取0或者1,其他值意味着无效。在这种情况下,通常我们就会使用枚举类型,来限制flag变量可以选择的值的范围。
我们还是举个例子。比如这么一个看起来很简单的程序。
#include<iostream>
int A = 0;
int B = 1;
int C = 2;
int main() {
int value = A;
std::cin.get();
}
如果我们希望value这个变量只能从A,B,C三者当中选一个值出来,那么我们可以使用枚举类型来写。
#include<iostream>
enum Example {A, B, C};
int main() {
Example value = A;
std::cin.get();
}
这样做有一个很明显的好处,就是代码看起来更加整洁了,而且我们将A,B,C这三个变量进行了分组,不至于我们写了一堆变量,散落的到处都是,到时候都不知道谁是谁了。
枚举类型所包含的值一定是整型的,但是因为整型是4byte,如果我们想节约一点内存,可以自定义枚举的类型为unsigned char/char,这样可以只使用一个byte。定义枚举类型的方式如下所示。
enum Example: unsigned char
{A, B, C};
需要注意的是,枚举类型不能是float,一定要是整型。
如果我们想要修改枚举类型的值,不让它只是0,1,2,那么我们可以直接在定义内修改它们的值。
我们可以把这个应用到我们之前写过的Log日志类当中,原始的日志类代码如下。
#include<iostream>
class Log {
private:
int m_LogLevel = LogLevelMessage;
public:
const int LogLevelError = 0;
const int LogLevelWarning = 1;
const int LogLevelMessage = 2;
public:
void SetLevel(int LogLevel) {
m_LogLevel = LogLevel;
}
void Warn(const char* message) {
if (m_LogLevel >= LogLevelWarning)
std::cout << "[Warning]: " << message << std::endl;
}
void Error(const char* message) {
if (m_LogLevel >= LogLevelError)
std::cout << "[Error]: " << message << std::endl;
}
void Message(const char* message) {
if (m_LogLevel >= LogLevelMessage)
std::cout << "[Message]: " << message << std::endl;
}
};
int main() {
Log log;
log.SetLevel(log.LogLevelMessage);
log.Warn("Hello");
log.Error("Hello");
log.Message("Hello");
std::cin.get();
}
我们可以看到,里面有一个LogLevel,我们希望这个值只能取到0,1,2,这正好是一个可以用枚举类型替代的地方。
class Log {
private:
int m_LogLevel = LogLevelMessage;
public:
enum LogLevel {
LogLevelError, LogLevelWarning, LogLevelMessage
};
public:
void SetLevel(LogLevel LogLevel) {
m_LogLevel = LogLevel;
}
void Warn(const char* message) {
if (m_LogLevel >= LogLevelWarning)
std::cout << "[Warning]: " << message << std::endl;
}
void Error(const char* message) {
if (m_LogLevel >= LogLevelError)
std::cout << "[Error]: " << message << std::endl;
}
void Message(const char* message) {
if (m_LogLevel >= LogLevelMessage)
std::cout << "[Message]: " << message << std::endl;
}
};
通过修改,我们得到了这样的代码。现在代码不仅看起来更简洁了,对不同的Loglevel进行了归纳,而且我们还可以防止输入不是Loglevel中的一员这种情况的发生,编译器会在我们编译之前就提醒我们这个问题了。