C++中的枚举(enum)
枚举类型(enumeration)是 C++ 中的一种派生数据类型,它是由用户定义的若干枚举常量的集合。
枚举是一个数值集合,是给一个值命名的一种方法。
如果想要使用整数来表示某些状态或者某些数值时,它非常有用。
不管怎么说,枚举其实就是一个整数,它的存在本质上是为了让代码更加干净,更加具有可读性。
看一个例子:
enum example {
Aa, Bb, Cc
};
数据类型本身的名字是以大写字母开头的,虽然这并非必须,但是绝大多数程序员都会釆用首字母大写的形式。
默认情况下,编译器设置第一个枚举量为 0,下一个为 1,以此类推。在上述示例中,Aa
的值将是 0,Bb
的值为 1,Cc
的值为2,也可以手动给每个枚举量赋值:
enum example {
Aa, Bb = 10, Cc
};
给Bb赋值为10后,Cc的值会变成11,这个需要注意。
还可以指定给枚举类型赋值的整数类型,枚举默认为32位整形,在某些情况下,甚至没必要用到32位,为了节省开销,甚至可以用8位整形:
enum example : unsigned char
{
Aa, Bb = 10, Cc
};
将类型指定成unsigned char后,枚举变量变成了8位整型,减少了内存使用。
需要注意的是,不能指定为float或者double等类型,因为枚举量必须是一个整数,float和double都不是整数。
要意识到,enum
语句示例实际上并没有创建任何变量,只是定义数据类型。当以后创建这个数据类型的变量时,它们看起来就是整数,并且这些整数的值被限制在与枚举集合中的符号名称相关联的整数上。
enum example
{
Aa = 0, Bb, Cc
};
example ex;
此语句的形式与其他任何变量定义一样,首先是数据类型名称,然后是变量名称。请注意,数据类型名称是example
,而不是enum example
。创建的变量ex
会被限定在0,1,2中,我们也可以避开编译器的限制,因为这种不属于物理上无法设定的东西,它本质上就是4个字节的整数,它只有四个字节的内存,我们可以把任何想要的东西放到那块内存中。
即使枚举数据类型中的值实际存储为整数,也不能总是将整数值替换为符号名称。例如,不能使用下面的语句将 Aa
赋值给 ex
:
ex = 0; //这种写法是不对的
但是,可以使用整数值而不是符号名称来测试枚举变量。例如,以下两个 if
语句是等效的:
if (ex == 0)
if (ex == Aa)
还可以使用关系运算符来比较两个枚举变量。
example ex1 = Aa, ex2 = Bb;
if (ex1 > ex2)
{
……
}
例子:
日志类,不使用枚举:
#include <iostream>
class Log
{
public:
const int LogLevelError = 0;
const int LogLevelWarning = 1;
const int LogLevelInfo = 2;
private:
int m_LogLevel = LogLevelInfo;
public:
void SetLevel(int level)
{
m_LogLevel = level;
}
void Warn(const char* message)
{
if (m_LogLevel >= LogLevelWarning)
std::cout << "[WARNING]:" << message << std::endl;
}
void Info(const char* message)
{
if (m_LogLevel >= LogLevelInfo)
std::cout << "[INFO]:" << message << std::endl;
}
void Error(const char* message)
{
if (m_LogLevel >= LogLevelError)
std::cout << "[ERROR]:" << message << std::endl;
}
};
int main()
{
Log log;
log.SetLevel(log.LogLevelWarning);
log.Warn("This is a warning!");
std::cin.get();
}
使用后,代码看起来干净很多:
#include <iostream>
class Log
{
public:
enum Level
{
LevelError = 0, LevelWarning, LevelInfo
};
private:
Level m_LogLevel = LevelInfo;
public:
void SetLevel(Level level)
{
m_LogLevel = level;
}
void Warn(const char* message)
{
if (m_LogLevel >= LevelWarning)
std::cout << "[WARNING]:" << message << std::endl;
}
void Info(const char* message)
{
if (m_LogLevel >= LevelInfo)
std::cout << "[INFO]:" << message << std::endl;
}
void Error(const char* message)
{
if (m_LogLevel >= LevelError)
std::cout << "[ERROR]:" << message << std::endl;
}
};
int s_Variable;
const int a = 1;
int main()
{
Log log;
log.SetLevel(Log::LevelInfo);
log.Warn("This is a warning!");
std::cin.get();
}