上一篇:《深入理解C++11》笔记-基于范围的for循环
本篇开始介绍第五章的内容:强类型枚举。
枚举enum的使用应该十分常见,用于定义同一类的数据。但是枚举其实存在一定的问题:
enum Male {
Name, Age, Birthday
};
enum Female {
Name, Age, Birthday
};
如上代码,如果两个枚举中定义了相同名称的枚举值,将会编译报错,因为枚举值并没有自己的名字空间。针对这种情况,往往会通过名字空间来分割枚举值的作用空间:
namespace Male{
enum Male {
Name, Age, Birthday
};
}
namespace FeMale {
enum Female {
Name, Age, Birthday
};
}
int main()
{
int a = Male::Name; // 使用时通过名字来决定使用哪个枚举值
return 0;
}
另外,枚举值总是可以被隐式转换为整形,这也会引起一些问题:
enum Level {
One,Two,Three,Four,Five
};
enum Type {
Low,Medium,High
};
class Password {
public:
Password(Level l, Type t) :level(l), type(t) {}
Level level;
Type type;
};
int main()
{
Password pwd(One, Low);
if (pwd.level < Medium) // 原意是比较密码等级,但是比较了密码类型,编译器也不会报错
{
}
return 0;
}
还有一点,枚举值所占用的空间大小也不确定。原来的标准规定,C++枚举的基础类型有编译器来具体制定实现,以下的代码输出是在Visual C++编译的:
enum A {A1 = 1, A2 = 2};
enum B { B1 = 1, B2 = 2, BMax = 0xFFFFFFF0U };
enum C { C1 = 1, C2 = 2, CMax = 0xFFFFFFFFFLL };
int main()
{
std::cout << sizeof(A1) << std::endl; // 4
std::cout << sizeof(B1) << std::endl; // 4
std::cout << sizeof(BMax) << std::endl; // 4
std::cout << BMax << std::endl; // -16,g++输出对应数值
std::cout << sizeof(CMax) << std::endl; // 4,g++输出8
std::cout << CMax << std::endl; // -1,g++输出对应数值
return 0;
}
从上面的代码可以分析出,g++会在需要的时候将枚举扩展为8位,且会根据枚举的类型变动是否有符号。而Visual C++始终为4位,且始终为无符号类型。
强枚举类型
强枚举类型是C++11针对以上的问题引入的一种新的枚举类型:
enum class Type{ // 在enum后面加上class关键字
Low,Medium,High
}
强枚举类型有几个特点:
- 强作用域,必须制定枚举类型才能使用。
- 转换限制,不能隐式转换为整形。
- 底层类型,默认底层类型为int,能够显式指定底层类型。
enum class Type : char{ // 指定类型
Low,Medium,High
}
下面我们看一下强枚举类型的具体例子:
enum class Level {
One,Two,Three,Four,Five
};
enum class Type {
Low,Medium,High
};
class Password {
public:
Password(Level l, Type t) :level(l), type(t) {}
Level level;
Type type;
};
int main()
{
Password pwd(One, Low); // 编译失败,必须使用枚举类型名字
Password pwd(Level::One, Type::Low);
if (pwd.level < Type::Medium) // 编译失败,必须使用同一枚举类型进行比较
{
}
if (pwd.level < Level::Three)
{
}
if (pwd.type > 1) // 编译失败,无法隐式转换为整形
{
}
if ((int)pwd.type > 1)
{
}
return 0;
}
另外,指定基本类型之后,各个编译器之间的实现就会相同,便于代码移植:
enum class B : unsigned int{ B1 = 1, B2 = 2, BMax = 0xFFFFFFF0U };
int main()
{
std::cout << sizeof(B::B1) << std::endl; // 4
std::cout << sizeof(B::BMax) << std::endl; // 4
std::cout << (unsigned int)B::BMax << std::endl; // 4294967280
return 0;
}