1.4 C++/CLI枚举
1.4.1 枚举的定义
与标准C++中定义枚举的方式不同,C++/CLI通过enum class组合关键字定义枚举类型。例如:
enum class Suit {Clubs, Diamonds, Hearts, Spades};
C++/CLI枚举类型的变量只能够被赋值为该枚举定义中的值。并且在访问该变量时,必须通过枚举类型名称限定当前使用的枚举值。例如:
Suit suit = Suit::Diamonds;
然而需要注意的是,在C++/CLI枚举中定义的所有常量都是对象,而标准C++枚举中枚举值为基本数据类型的值。实际上,C++/CLI枚举中的值都默认是System::Int32类型的对象,其中封装了int类型的值。
另外,可以在C++/CLI程序中使用与标准C++枚举相同的语法,它们的行为将与在本地C++程序中的行为相同。本地C++枚举的语法在C++/CLI程序中得到了扩充,并允许显式地指定枚举常量的类型。但是,在C++/CLI程序中最好还是使用C++/CLI枚举。
【例1.7】 C++/CLI枚举的使用示例。定义一个枚举值,并将这些枚举值强制转换为与其对应的整型值并输出。代码如下:
// Ex1_7.cpp : 主项目文件 #include "stdafx.h" using namespace System; enum class Suit {Clubs, Diamonds, Hearts, Spades}; int main(array<System::String ^> ^args) { Suit suit = Suit::Clubs; int value = safe_cast<int>(suit); Console::WriteLine(L"Suit为: {0},且值为: {1}", suit, value); suit = Suit::Diamonds; value = safe_cast<int>(suit); Console::WriteLine(L"Suit为: {0},且值为: {1}", suit, value); suit = Suit::Hearts; value = safe_cast<int>(suit); Console::WriteLine(L"Suit为: {0},且值为: {1}", suit, value); suit = Suit::Spades; value = safe_cast<int>(suit); Console::WriteLine(L"Suit为: {0},且值为: {1}", suit, value); return 0; }
当Ex1_7程序运行后,枚举中的每个常量都对应了一个常量值,其中第一个枚举常量默认值为0,而其他枚举常量的值依次递增。Ex1_7项目的运行结果如图1.11所示。
图1.11 Ex1_7项目的运行结果
1.4.2 枚举的常量
虽然C++/CLI枚举中的值都默认是System::Int32类型的对象,但是还可以将其指定为如表1.5所示的任意一种基本类型。
表1.5 C++/CLI枚举常量可用的数据类型
在指定枚举常量的类型时,可以在定义枚举的类型名称之后通过冒号(“:”)来说明常量的类型。例如,下面的代码将枚举中的常量指定为System::Char类型,那么其对应的基本类型为char类型。
enum class Face : char { Ace, Two, Three, Four, Five, Six, Seven, Eight, Nine, Ten, Jack, Queen, King };
一般情况下,在指定枚举常量的类型后,枚举中第一个枚举常量的默认值为0,而后面的枚举常量依次递增。当然,也可以为枚举类型中的一个或全部枚举常量都指定对应的值。例如,如果将Face枚举中Acer常量指定为1,那么后面枚举常量的值将都依次加1。
enum class Face1 : char { Ace=1, Two, Three, Four, Five, Six, Seven, Eight, Nine, Ten, Jack, Queen, King }; enum class Face2 : char { Ace=14, Two=2, Three, Four, Five, Six, Seven, Eight, Nine, Ten, Jack,Queen,King};
1.4.3 枚举常量的运算
由于在定义C++/CLI枚举时为枚举常量指定了对应的值,所以可以对枚举常量进行各种运算(枚举常量类型为bool类型时除外)。
例如,可以通过“++”或“--”运算符对枚举常量进行递增或递减运算,从而改变枚举常量的值。但是,通过递增或递减后的枚举变量完全不会对运算结果进行有效性验证,因此需要在程序中确保其对应的枚举值。
Face card = Face::Ten; // card的值为Face::Ten card++; // card的值为Face::Jack
同时,还可以对枚举常量进行算术运算,如加、减、乘和除等。但是,不能直接将枚举常量与其他非枚举类型的常量进行运算,这是因为算术运算两端的操作数的类型不同,并且它们也不能自动转换成相同的类型,所以需要通过类型强制转换来进行算术运算。例如:
card = card – Face::Two; // card的值为Face::Eight card = card – safe_cast<Face>(2); // card的值为Face::Six
同样,还可以通过关系运算符比较两个枚举常量的值,其比较结果将产生一个bool类型的值。例如:
if (card < Face::Eight) Console::WriteLine(L"Card的值小于8点"); if (card > Face::Eight) Console::WriteLine(L"Card的值大于8点"); if (card != Face::Eight) Console::WriteLine(L"Card的值不等8点"); if (card == Face::Eight) Console::WriteLine(L"Card的值等于8点");
另外,还可以将枚举定义成为标识位,这种标识位可用其中的某些位记录一种或多种事件。在将枚举定义成为表示标识位时,需要通过[Flags]属性修饰。其中,属性是添加到程序语句中的附加信息,用于指示编译器以何种方式修改代码或插入代码。例如,定一个枚举标识位的方式如下:
[Flags]enum class FlagBits{Ready=1,ReadMode=2,WriteMode=4,EOF=8,Disable=16};
对于表示标识位的枚举常量,可以通过位运算符对这些常量进行运算。例如,可以使用或运算符(“|”)组合标识位,或者通过取反运算符(“~”)获得某个标识位取反的值。
FlagBits status = FlagBits::Ready | FlagBits::ReadMode | FlagBits::EOF; status = status &~FlagBits::Ready;