通常我们会把一些相关的数值常量定义成一个enum类型,这样可以加强类型安全,同时使程序的可读性更强。进行.NET时代,一种公共类型系统中也定义了enum类型,但同时也增强了其功能,真正将其赋予了面向对象的特征,成为.NET中的第一等公民。但C++/CLI中允许托管代码和非托管代码共存,因此在使用中难免有些混淆。笔者试图从原理中加以剖析。
先看一个例子:
// 标准C++中的enum声明
enum Color {Red, Blue, White} ;
// C++/CLI中的声明
enum class MColor1 {Red,Blue,White} ;
enum struct MColor2 {Red,Blue,White} ;
void main()
{
// 使用标准C++中的enum
Color myColor0 = Red;
// 使用C++/CLI中的enum
MColor1 myColor1 = MColor1::Blue;
MColor2 myColor2 = MColor2::White;
}
该程序只是简单地声明了enum类型,然后使用它。
在标准C++中只使用一个关键词enum,而在C++/CLI中则使用组合关键词如enum class。
编译上面的程序(cl /clr:safe MyEnum.cpp),我们来检查生成的中间代码。
根据上图我们可以得出以下结论:
n enum class和enum struct是等价的。
n 三种类型都派生自System.Enum
n 每种类型都有一个内在数据类型。一般缺省是int,当然用户根据需要可以声明其他的数据类型,如果我声明下面的类型
在中间代码中会是:
很显然这时的内在类型变成了bool。
从图上矩形线框中我们也可看到有一点C++/CLI与传统的enum不同。托管类型的enum确实是生成了新的类型,我们称之为迭代子(enumerator)。正是这个原因,托管enum可以充分利用System.Enum的更多方法和属性。下面的代码就是枚举名称
for each(String ^ name in names)
{
Console::WriteLine(name);
}
也正因为如此,传统的C++中,应该这样使用:
Color myColor0 = Red;
而不能这样:
Color myColor0 = Color::Red;
而且在上面的例子中,如下声明编译器会报“重定义”的错误:
enum Color{Red, Blue, White};
enum OtherColor{Red,Gray,Orange};// error C2365: 'Red' : redefinition;
而反观.NET中的枚举则无此限制,因为在使用中我们用了类型限制(如MColor1::)。