我不太习惯使用标志进行编程,但我想我刚刚发现了它们有用的情况:
我有几个对象将自己注册为某些事件的侦听器。它们注册的事件取决于构造它们时发送给它们的变量。我认为一个很好的方法是发送按位或连接的变量,如下所示:可抓取 |然后,在构造函数中,对象可以检查设置了哪些标志并将其自身注册为这些标志的侦听器。
但这就是我感到困惑的地方。最好,标志位于枚举
中。但这也是一个问题。如果我们有这些标志:
enum
{
TAKES_DAMAGE,/* (0) */
GRABBABLE, /* (1) */
LIQUID, /* (2) */
SOME_OTHER /* (3) */
};
那么发送标志 SOME_OTHER
(3) 将与发送 GRABBABLE | GRABBABLE | 相同。液体,不是吗?
你究竟如何处理这些东西?
I'm not very used to programming with flags, but I think I just found a situation where they'd be useful:
I've got a couple of objects that register themselves as listeners to certain events. What events they register for is dependent on a variable that is sent to them when they are constructed. I think a nice way to do this would be to send bitwise OR connected variables, like such: TAKES_DAMAGE | GRABBABLE | LIQUID
, etc. Then, in the constructor, the object can check what flags are set and register it self as listener for the ones that are.
But this is where I get confused. Preferably, the flags would be in an enum
. But that is also a problem. If we have got these flags:
enum
{
TAKES_DAMAGE,/* (0) */
GRABBABLE, /* (1) */
LIQUID, /* (2) */
SOME_OTHER /* (3) */
};
Then sending the flag SOME_OTHER
(3) will be the same as sending GRABBABLE | LIQUID
, will it not?
How exactly do you deal with this stuff?
发布评论
评论(6)
您的枚举需要是 2 的幂:
或者以更易读的方式:
为什么?因为您希望能够组合不重叠的标志,并且还能够执行以下操作:
...如果枚举值如下所示,则该方法有效:
所以,假设您已将
myVar
设置为可抓取 | TAKES_DAMAGE
,以下是当您需要检查 GRABBABLE 标志时它的工作原理:如果您将
myVar
设置为LIQUID | SOME_OTHER
,该操作将导致:Your enumeration needs to be powers of two :
Or in a more readable fashion :
Why ? Because you want to be able to combine flags with no overlapping, and also be able to do this:
... Which works if the enumeration values look like this :
So, say you've set
myVar
toGRABBABLE | TAKES_DAMAGE
, here's how it works when you need to check for the GRABBABLE flag:If you'd set
myVar
toLIQUID | SOME_OTHER
, the operation would have resulted in :存储标志的另一种方法是根本不关心底层类型。使用枚举时,枚举值默认存储为无符号整数,在普通计算机上为 32 位。这给了你 32 个可能的标志:虽然肯定很多,但在某些情况下这还不够。
现在你可以这样定义你的标志集:
如果你从未遇到过这种情况,“:1”部分告诉编译器仅使用 1 位来存储此结构成员。
现在您可以定义一个变量来保存标志,并使用这些标志:
此方法允许您无限制地定义任意数量的标志,并且您可以随时扩展标志集而不必担心溢出。缺点是测试标志的子集更加麻烦并且需要更多代码。
another way of storing flags is to not bother with the underlying type at all. when using an enum, the enum values are stored by default into an unsigned int, which is 32 bits on a common computer. this gives you with only 32 possible flags: while certainly much, there are some cases where it is not sufficient.
now you can define your flag set this way:
if you never encountered this, the ': 1' part tells the compiler to only use 1 bit to store this struct member.
now you can define a variable to hold the flags, and work with those flags:
this method allows you to define any number of flags, without limitation, and you can extend your flag set at any time without fearing an overflow. the drawback is that testing a subset of the flags is more cumbersome and necessitate more code.
是的。相反,让你的枚举成员的幂为 2:
Yes. Instead, make your enum members powers of 2:
您应该使标志仅为 2 的幂,即每个标志都是您存储的任何数据类型中的一个位,并且当您按位或时没有任何重叠。
You should make the flags only powers of two, i.e. each is a bit in whatever data type you're storing this in, and nothing overlaps when you bitwise OR.
你不能只在枚举中设置值吗?
然后,只需对它们执行按位或即可。
Can't you just set the values in the enum?
Afterwards, just perfom bit-wise OR on them.
你需要
you need