微信公众号: 星点课堂
新浪微博:女儿叫老白
网易云课堂:女儿叫老白
网易云课堂免费课程:《C++跨平台开发中的编译错误》
-----------------------------------------------------------------------------(3.8.3, 3.8.4)
-- 枚举 enum
在编程过程中,我们经常用到一些整数型常量,比如参数类型id,这时我们可以采用宏定义的方式把常量定义为宏定义。如果这些常量之间有计算关系(比如后一个的值=前一个值+1),我们就可以使用枚举。枚举的语法如下:
enum 枚举类型名 {
自定义枚举字符串1= xxx,
自定义枚举字符串2= xxx,
自定义枚举字符串3= xxx,
};
比如:
// 枚举:菜单项ID
enum EMenuID {
EMENUID_NULL = 0, // 无效菜单项
EMENUID_FILEOPEN, // 打开文件=1
EMENUID_SAVE, // 保存=2
EMENUID_CUSTOM=1000, // 用户自定义菜单项起始值
EMENUID_CUSTOM_WRITEDB, // 自定义菜单:写入数据库=1001
};
上述的枚举类型EMenuID,包含了4个枚举值,第一个是“EMENUID_NULL = 0”,表示无效菜单项,当然,您也可以写成EMENUID_NULL = 2.。这跟您的实际需求有关。
枚举值以”,”结束。
EMENUID_FILEOPEN和EMENUID_SAVE是两个新枚举值,因为没有给他们赋值,所以他们的值依次等于前一个值+1。
我们也可以为后面的枚举项直接赋值,比如:
EMENUID_CUSTOM=1000
这表示用户自定义菜单项从1000开始。因此EMENUID_CUSTOM_WRITEDB=1001.
-- 联合-union
我们有时候会定义一些变量,但是这些变量是互斥使用的,比如定义一个事项结构时,我们可能要处理操作类事项:
struct sEventOperate {
string strOperator; // 操作人员
string strTime; // 操作时间
string strJob; // 操作内容
};
也需要处理告警事项:
struct sEventAlarm {
time_t tmAlarm; // 报警时间
int level; // 报警等级
string strInfo; // 报警内容
};
那么我们的类中需要用到操作类事项和告警事项,但是这两种事项又不会同时出现,我们就可以用联合的方式进行处理。
我们先定义事项类型:
enum EEventType {
EEventType_NULL = 0, // 无效事项
EEventType_Operate, // 操作类事项
EEventType_Alarm, // 告警类事项
};
struct sEventBody {
EEventType evtType; // 事项类型
union {
sEventOperate evtOperate; // 操作类事项
sEventAlarm evtAlarm; // 告警类事项
};
};
这样,sEventBody就可以对两种事项类型进行处理,比如:
sEventBody evtBody;
swtich (evtBody.evtType) {
case EEventType_Operate:
evtBody.evtOperate; // 对操作类事项进行处理
break;
case EEventType_ Alarm:
evtBody. evtAlarm; // 对告警类事项进行处理
break;
default:
break;
}
sEventBody在内存中的尺寸 = evtType + max(evtOperate, evtAlarm)。也就是evtType的尺寸 加上 evtOperate, evtAlarm两者中尺寸大的那个。
------------------------ 总结 ----------------------
1. 尽量使用枚举(enum)而不是常量(具体的数字,比如0x3377),在通信时,如果通信双方均使用常量,那么这些常量就变成魔法数字。因为代码的后续维护人员可能根本不知道这些常量的具体含义。
2.枚举项可以根据需要随时定义为某个具体值。但是一定要给前面的枚举项留下足够的空间,否则就可能出现前面不断增加的枚举项已经远远超过了您定义的当前值。比如
enum eMenuId {
EMENUID_NULL = 0, // 无效菜单项
EMENUID_FILEOPEN, // 打开文件=1
EMENUID_SAVE, // 保存=2
EMENUID_CONFIG, // 配置=3,注:这个枚举项时后来增加的
EMENUID_MODIFY, // 修改=4,注:这个枚举项时后来增加的
EMENUID_HELP, // 帮助=5,注:这个枚举项时后来增加的
EMENUID_LOGIN, // 注册=6,注:这个枚举项时后来增加的
EMENUID_CUSTOM=5, // 用户自定义菜单项起始值,注:该数值已经有问题
};
3.使用联合(union)时要小心,因为起初定义联合时,可能对象的尺寸很小,但是随着功能的增加或者改变,联合的对象所占据的尺寸可能越来越大,当联合的实体(用联合定义的对象)比较多时,它占据的内存甚至超乎想象。