C++使用颇具特色的枚举(enumeration)声明给定名字的常量,这和C#以及最近版本的Java所提供的方式相似。现在,假定我们需要在程序中存储一周中的一天:
enum DayWeek
{
Sunday, Monday, Tuesday, Wednesday, Thursday, Friday, Saturday
};
通常情况下,我们将会把这一声明放在一个头文件中,或者甚至会放进一个类中。上面的声明可以简单地与下列常量的定义相等价:
const int Sunday = 0;
const int Monday = 1;
const int Tuesday = 2;
const int Wednesday = 3;
const int Thursday = 4;
const int Friday = 5;
const int Saturday = 6;
通过使用枚举结构,我们可以在后面声明一些DayOfWeek类型的变量或者参数,并且编译器将可以确保只对那些来自DayOfWeek枚举中的变量才赋值。例如:
DayOfWeek day = Sunday;
如果我们不关心类型安全性(type safety),那么也可以写作:
int day = Sunday;
需要注意的是,为了读取DayOfWeek枚举中的Sunday常量,我们只需写作Sunday即可,而不必写成DayOfWeek::Sunday。
默认情况下,编译器会从0开始给枚举中的常数值分配连续的整数型。如果需要,也可以把它们指定成其他的常量值:
enum DayOfWeek
{
Sunday = 628,
Monday = 616,
Tuesday = 735,
Wednesday = 932,
Thursday = 852,
Friday = 607,
Saturday = 845
};
如果没有给某个枚举元素制定值,那么该元素机会用前面元素的取值加1来作为自己的取值。有时候,枚举用于声明整形常量,这时,我们通常会忽略枚举的名字:
enum
{
FirstPort = 1024,
MaxPorts = 32767
};
另外一种常见的枚举用法是用来表达选项的集合。我们以那个Find对话框为例,假定它有四个复选框,分别用来控制查询算法(使用通配符、区分大小写、向前查找以及循环查找)。我们可以用一个以2的幂次方为值得枚举常量来表示这一算法:
enum FindOption
{
NoOptions = 0x00000000,
WildcardSyntax = 0x00000001,
CaseSensitive = 0x00000002,
SearchBackward= 0x00000004,
WrapAround = 0x00000008
};
每个选项通常都称为“标记”(flag)。我们可以使用按位“|”或者“|=”运算符来组合这些标记:
int options = NoOptions;
if(wildcardSyntaxCheckBox ->isChecked())
{
options |= WildcardSyntax;
}
if(caseSensitiveCheckBox ->isChecked())
{
options |= CaseSensitive;
}
if(searchBackwardCheckBox ->isChecked())
{
options |= SearchBackward;
}
if(wrapAroundCheckBox ->isChecked())
{
options |= WrapAround;
}
可以使用按位“&”运算符来测试是否选中了某个标记:
if(options & CaseSensitive)
{
// case-sensitive search
}
一个类型为FindOption的变量每次只能包含一个标记。使用“|”对多个标记符组合的结果就是一个普通的整数。但不幸的是,这样做并不具备类型安全性: 如果一个函数期望通过一个 int 参数获得FindOptions的组合结果,但接收的却是Saturday,而编译器却不会对此报错。Qt使用QFlags<T>来对它自己的标记类型的数据提供类型安全性保障。当我们定义一些自定义类型时,也是可以使用这个类的。更为详尽的内容请参考QFlags<T>的在线文档。
网友评论