枚举值和类型都是全局可见的, 与正常C++的namespace、类等都是格格不入的,并且还容易导致冲突。
enum Type { General, Light, Medium, Heavy };
enum Category { General, Pistol, MachineGun, Cannon };
如果在相同作用域同时能访问到枚举Type和Category,则General会冲突。
当然我们可以通过namespace对全局枚举进行分隔。但使用时如果忘记写namespace,也还是会报错。
namespace T {
enum Type { General, Light, Medium, Heavy };
}
namespace {
enum Category { General };
}
#include
int main()
{
T::Type t = T::Heavy;
t = General; //error.无法赋值,不能将匿名的Category::General赋值给T::Type
if (t == General) { //仅对于匿名命名空间可以直接使用General。
std::cout << "equal" << std::endl;
}
else {
std::cout << "not equal" << std::endl;
}
system("pause");
return 0;
}
因为C的枚举是基于常量数值设计的,所以总是可以被隐式转为int,所以在算数运算(没有什么意义)和比较运算时,容易出错。(注意无法赋值)
这是因为隐式转换为整型后,没有了类型限制,则可以随意比较和算数运算。
#include
using namespace std;
enum Type { General, Light, Medium, Heavy };
//enum Category { General, Pistol, MachineGun, Cannon }; // 无法编译通过,重复定义
了General
enum Category { Pistol, MachineGun, Cannon };
struct Killer {
Killer(Type t, Category c) : type(t), category(c){}
Type type;
Category category;
};
int main() {
Killer cool(General, MachineGun);
// ...
// ...其他很多代码...
// ...
if (cool.type >= Pistol)
cout << "It is not a pistol" << endl;
// ...
cout << is_pod::value << endl; // 1
cout << is_pod::value << endl; // 1
return 0;
}
// 编译选项:g++ -std=c++11 5-1-2.cpp
C++所基于的“基础类型”由编译器决定,也就意味着,他的符号性和存储空间是不确定的。
#include
using namespace std;
enum C { C1 = 1, C2 = 2};
enum D { D1 = 1, D2 = 2, Dbig = 0xFFFFFFF0U };
enum E { E1 = 1, E2 = 2, Ebig = 0xFFFFFFFFFLL};
int main() {
cout << sizeof(C1) << endl; // 4
cout << Dbig << endl; // 编译器输出不同, g++:4294967280,Vs2017:-16
cout << sizeof(D1) << endl; // 4
cout << sizeof(Dbig) << endl; // 4
cout << Ebig << endl; // g++:68719476735,vs2017:-1
cout << sizeof(E1) << endl; // 8
return 0;
}
// 编译选项:g++ 5-1-4.cpp
上面可以看到如果够用的话(Dbig),采用4字节存储。不够用的时候会自动扩展为8字节存储(Ebig),且对于Ebig和Dbig而言不同的编译器返回的值不同,这是因为符号性不一样导致。
enum class/struct [enum-name] [:base-type]{};
可以看到基本上就是为了解决C枚举的三个缺陷而设计的。
强枚举类型也是可以匿名的,但是由于其枚举成员需要通过作用域访问,因此匿名强枚举类型可能无法访问成员,当然也可以使用decltype获取类型。
对于C枚举,默认依旧由编译器实现基础类型,但是C++11允许其和强枚举类型一样,指定基础类型。
enum Type: char { General, Light, Medium, Heavy };
其次,在C++11中,枚举成员的名字除了会自动输出到父作用域,也可以在枚举类型定义的作用域内有效。
enum Type { General, Light, Medium, Heavy };
Type t1 = General;
Type t2 = Type::General;