C ++枚举标志用法

时间:2014-04-07 16:26:02

标签: c++ enums

我已经用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);
}

我是一个相当新的程序员,所以我确信我使用了不良做法或者遗漏了一些明显的东西。不要害羞地告诉我。

3 个答案:

答案 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 * ba & b相同。