我已经用Google搜索了,但似乎没有立即可用的明确答案。我试图弄清楚C ++中枚举标志的正确用法。我正在研究基于2D平铺的平台游戏引擎,我想给每个平铺标志确定哪些边缘可以与之碰撞。
在一个文件中我有:
enum CollidableEdges
{
TopEdge = 1,
RightEdge = 2,
BottomEdge = 4,
LeftEdge = 8
};
如何在对象中实际调用这些标志并在以后的逻辑中使用它们?在我看过的例子中,在操作标志时,它似乎没有在初始列表之外的任何地方声明枚举。有人可以澄清究竟发生了什么以及如何使用它?例如,在创建具有如下定义的新Tile对象时:
class Tile: public Entity
{
public:
Tile(std::string obstacleTexture, int, int);
}
我是一个相当新的程序员,所以我确信我使用了不良做法或者遗漏了一些明显的东西。不要害羞地告诉我。
答案 0 :(得分:0)
CollidableEdges
是一种类型,您可以在任何可以使用类型的地方使用它(例如,它可能是您方法中某个参数的类型。
枚举的标签是在枚举的包含范围内有效的标识符。例如,如果您在class XX
中定义枚举,则可以使用XX::TopEdge
你可以转换为/来自int,但最好检查(例如切换/大小写)而不是从int进行盲转。
转换为int会产生与标签关联的值。这是静态const整数常量的替代方法。因此,例如,在每个标签与逐位不相交值相关联的示例中,您可以使用按位或(例如TopEdge | LefEdge)组合标签[但仅因为它们是不相交的整数值。)
答案 1 :(得分:0)
有人可以澄清究竟发生了什么以及如何使用它吗?
初始化特定位
uint8_t flags = uint8_t(TopEdge) | uint8_t(LeftEdge);
设置特定位
flags |= uint8_t(BottomEdge);
清除特定位
flags &= ~(uint8_t(TopEdge) | uint8_t(LeftEdge));
测试特定位
if(flags & uint8_t(BottomEdge) > 0) { // Flag is set (BottomEdge)
}
您需要强制转换它的原因是,如果您有TopEdge | LeftEdge
这样的表达式,编译器将不会接受原始enum
类型作为结果。
要摆脱演员表,你还可以定义一个重载的operator|()
,operator&()
等:
CollidableEdges operator|(CollidableEdges left, CollidableEdges right) {
return static_cast<CollidableEdges>(static_cast<unsigned>(left) |
static_cast<unsigned>(right));
}
// etc.
允许简单地写
CollidableEdges edges = TopEdge | LeftEdge;
注意:强>
虽然上述陈述可以正常工作,但恕我直言,它们对预期的语义提供了不良的可读性。我个人更喜欢以下解决方案:
enum class CollidableEdgeBitPos : size_t {
TopEdge ,
RightEdge ,
BottomEdge ,
LeftEdge
};
typedef std::bitset<4> CollidableEdges;
CollidableEdges edges;
edges[CollidableEdgeBitPos::RightEdge] = true;
edges[CollidableEdgeBitPos::BottomEdge] = false;
答案 2 :(得分:0)
鉴于数值,它看起来像你的枚举 用于定义位掩码。在这种情况下,通常的程序 将为他们重载相关的操作员,这样做 你可以恰当地使用它们:
inline CollidableEdges
operator|( CollidableEdges lhs, CollidableEdges rhs )
{
return static_cast<CollidableEdges>(
static_cast<unsigned>( lhs) | static_cast<unsigned>( rhs ) );
}
等。 (您需要|
,|=
,&
,&=
和~
。)这些
运算符通常应与枚举位于同一标题中
定义。然后使用它们的对象也会占用
一个CollidableEdge
作为参数:
Tile::Tile( std::string const& texture, CollidableEdge edges )...
等
传统上,枚举常量的名称是
与enum本身在同一范围内定义;在C ++ 11中,你也是
有可能将它们限制在枚举中
声明enum class CollidableEdge
,而不是
enum CollidableEdge
;在这种情况下,你必须指定
CollidableEdge::TopEdge | CollidableEdge::LeftEdge
,而不是
而不只是TopEdge | LeftEdge
。 (另一方面,这意味着
他们不会与你想要的任何其他符号发生冲突
定义。)
最后,鉴于&#34;错误&#34;我经常|
和&
的先行
发现将运算符+
,-
和*
定义为很方便
好吧,a + b
相当于a | b
(你正在添加值
集合),a - b
相当于a & ~ b
(你正在减去
集合中的值和a * b
与a & b
相同。