C++工程项目中常见的写法与解释——多种状态值的混合(按位处理)篇

一般来说,对于一个类而言,其状态的表达形式有很多,比如使用enum枚举

enum CLASS_STATUS{status1=0,status2,status3}

但假如这个类有多种状态,使用多个enum枚举状态值,效率往往没有按位计算来的更高。

假如有一个类,animal动物,有行动状态(飞,走,游),有身形状态(大,中,小),有颜色状态(红,白,蓝),我们可以这样设定:

#define animal_action_status_fly					0x00000001
#define animal_action_status_walk					0x00000002
#define animal_action_status_swim					0x00000004

#define animal_action_status_big					0x00000010
#define animal_action_status_medium					0x00000020
#define animal_action_status_small					0x00000040

#define animal_action_status_red					0x00000100
#define animal_action_status_white					0x00000200
#define animal_action_status_blue					0x00000400

当我们想表示一个中等身形的,会飞的蓝色动物,我们可以这样表示:

animal_action_status_medium | animal_action_status_fly	| animal_action_status_blue

按位取或是对二进制而言的,所以这里的按位取或,是要将十六进制数值转换成二进制,从而计算。
十六进制的一位0~F转化成二进制为:0000~1111
而00、10、20、30~F0转化成二进制为:0000 0000~1111 0000
由此我们可以发现,如果进行如下计算
获取结合状态值

m_status = animal_action_status_medium | animal_action_status_fly

会得到
0x00000020 | 0x00000001
转化成二进制为
0010 0000 | 0000 0001
按位取或,结果为0010 0001,是两种状态结合的唯一二进制结果,
如若转化成十六进制,则为0x00000021,
既方便查看唯一状态值,又方便查验到底是哪几种状态的结合值。

设定的状态值,如果单一状态的数量在1~F(1~15个)时,每个状态占一位是可行的,但如果单一状态超过这个数值,就用两位表示一个状态即可。
比如,上面动物的例子,颜色状态不止有3个,有24个,如果第0个值该状态值表示为0x00000100,那么第24个的十六进制值表示为0x00001800

所以实际使用时,可根据实际情况,设计状态占的位数。

取消某个状态值

m_status &= ~ animal_action_status_fly

验证结合状态值
现在得到了一个结合后的状态值,如何知道这个animal都包含了哪些属性(状态)呢?

m_status=0x00000021
bool check(unsigned combinedStatus)
{
	return (m_status & combinedStatus) !=0;
}

假如我想验证这个animal会不会走路walk,那么传入animal_action_status_walk进去,
计算 0x00000021 & 0x00000002 转为二进制计算为:
0010 0001 & 0000 0010 = 0000 0000 则函数返回false,即不包含walk状态。

假如我想验证这个animal身形是不是medium,那么传入animal_action_status_medium进去,
计算 0x00000021 & 0x00000020 转为二进制计算为:
0010 0001 & 0010 0000 = 0010 0000 则函数返回true,即包含medium状态。

需要注意的是
为了验证结合状态值,单个状态值的赋值,十六进制下只能是1、2、4、8、10、20、40、80……这样的数。
原因是,当用十六进制的一位表示一个状态值时,转换成二进制进行计算时,值为:
0x0001->0001
0x0002->0010
0x0004->0100
0x0008->1000
所以只能表达4个值,如果使用了这4个值以外的值,如0x0003->0011,
在验证结合状态值时,将会出现错误,比如这样定义

#define animal_action_status_climb					0x00000003

然后验证

m_status = animal_action_status_fly	//0x00000001

0x00000003 & 0x00000001 转为二进制计算
0011 & 0001 = 0001 为非0数,则check函数返回true,代表m_status包含climb状态,而实际上他只有fly的状态。
所以为了验证时不出错,如果十六进制中每一位代表一个状态时,状态值只能写1、2、4、8,才能保证转化成二进制计算按位与时,不会出错。
这也就意味着,每种状态只允许4个值,当然可以扩展成两位十六进制来表示一个状态,比如1、2、4、8、10、20、40、80,这样就允许8个值了。

实际上这种方式的可玩性有各种各样,可以根据实际情况来声明和使用,以上只是给一个思路。

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值