0%

C++ 11 enum class

代码展示

C++ 11 的enum class在使用上与传统的enum有什么不同呢,这里先通过代码来一目了然地展示:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
#include <iostream>
using namespace std;

// Old C++ Enum
enum OldSchoolEnum
{
ValA = 0,
ValB = 100,
ValC = 10000,
};

// C++ 11 Enum Class
enum class ModernEnum : short // We can explicit specify the underlying type
{
ValA = 0,
ValB = 100,
ValC = 10000,
};

int main() {
//Usage of OldSchoolEnum
OldSchoolEnum myEnum1 = ValB; //ValB is in global namespace. Bad!
int myInt = myEnum1; //Can implicit cast to int. Bad!
//myEnum1 = myInt; //ERROR! Can't implicit cast int to enum
myEnum1 = static_cast<OldSchoolEnum>(myInt); //We can do it by explicit cast
std::cout << myEnum1 << std::endl; //Print 100

//Usage of ModernEnum
ModernEnum myEnum2 = ModernEnum::ValB; //ValB is in class namespace. Good!
//myInt = myEnum2; //ERROR! Can't implicit cast myEnum2 to int
myInt = static_cast<int>(myEnum2); //We can do it by explicit cast
//myEnum2 = myInt; //Also ERROR!
myEnum2 = static_cast<ModernEnum>(myInt); //Also success by explicit cast
//std::cout << myEnum2 << std::endl; //ERROR! Can't implicit myEnum2 to any numerical type
using ModernEnum_underlying_t = std::underlying_type<ModernEnum>::type; //First, we get the underlying type of ModernEnum
std::cout << static_cast<ModernEnum_underlying_t>(myEnum2) << std::endl;//Second, We implement cout by cast to underlying type

return 0;
}

上面的代码涵盖了大部分的注意点,直接看注释即可。

前向声明

除此之外,enum class还支持前向声明,以便于减少依赖,减少编译时间。可以参考以下代码:

Orientation.h
1
2
3
4
5
6
7
8
9
10
#pragma once
enum class Orientation
{
FRONT = 1,
BACK = 2,
LEFT = 3,
RIGHT = 4,
TOP = 5,
DOWN = 6
};
BoxFace.h
1
2
3
4
5
6
7
8
9
10
11
12
13
14
#pragma once
//Don't need to #include "Orientation.h"
//Forward declaration of enum class
enum class Orientation;

class BoxFace
{
public:
BoxFace(Orientation ori);
void printOrientation();

private:
Orientation myori;
};
BoxFace.cpp
1
2
3
4
5
6
7
8
9
10
11
#include <iostream>
#include "BoxFace.h"
BoxFace::BoxFace(Orientation ori)
{
myori = ori;
}

void BoxFace::printOrientation()
{
std::cout << static_cast<std::underlying_type<decltype(myori)>::type>(myori) << std::endl;
}
main.cpp
1
2
3
4
5
6
7
#include "BoxFace.h"
#include "Orientation.h"
int main() {
//Usage of BoxFace
BoxFace face(Orientation::LEFT);
face.printOrientation();
}

这里我们有BoxFace类,其包含一个Orientation枚举值的成员变量。如果使用原有的enum,我们需要在BoxFace类的头文件中包含Orientation的头文件,也就是说在定义枚举变量前,要知道该枚举类型的定义;而使用enum class,我们只需要进行一个前向声明即可,将Orientation.h的包含移到了BoxFace的源文件中。这样做有什么好处我也不过多介绍了,具体可以看前向声明的相关资料。

总结

  • enum不限制其中枚举值的命名空间,而enum class中的枚举值被包含在该enum的命名空间中。
  • enum class可以手动指定其枚举值的存储类型,默认为32位整型,使用std::underlying_type可以获取该类型。
  • enum可以隐式转换到整型,enum class必须显式转换。
  • 要使整型转换到enum或enum class,都必须通过显式转换。
  • enum class可以前向声明。