枚举位域容器类 我试图编写一个小类来更好地理解C++中的位标志。但有些事情没有解决。它打印错误的值。问题在哪里?我是否误解了如何添加标志?或者检查位字段中是否有它们

枚举位域容器类 我试图编写一个小类来更好地理解C++中的位标志。但有些事情没有解决。它打印错误的值。问题在哪里?我是否误解了如何添加标志?或者检查位字段中是否有它们,c++,enums,bit-fields,bitflags,C++,Enums,Bit Fields,Bitflags,代码如下: #include <iostream> enum flag { A = 1, B = 2, C = 4 }; class Holder { public: Holder() : m_flags(A) {} ~Holder() {} void add_flag(flag f) { m_flags |= f; } bool has_flag(flag f) { return ((m_flags&f)==f); }

代码如下:

#include <iostream>

enum flag
{
    A = 1, B = 2, C = 4
};

class Holder
{
public:
    Holder() : m_flags(A) {}
    ~Holder() {}

    void add_flag(flag f) { m_flags |= f; }
    bool has_flag(flag f) { return ((m_flags&f)==f); }
    void remove_flag(flag f) 
    {
        unsigned int flags = 0;
        for (int i = 1; i<=(int)C; i *= 2)
        {
            if ((flag)i!=f && has_flag(f))
                flags |= f;
        }
        m_flags = flags;
    }

    void print()
    {
        std::cout << "flags are now: " << m_flags << " | holding: "; 
        for (int i = 1; i<=(int)C; i *= 2)
        {
            if (has_flag((flag)i))
                std::cout << i << " ";
        }
        std::cout << std::endl;
    }

private:
    unsigned int m_flags;
};

int main()
{
    Holder h;
    h.print(); // should print 1

    h.add_flag(B);
    h.print(); // should print 1 2

    h.remove_flag(A);
    h.print(); // should print 2

    h.add_flag(C);
    h.print(); // should print 2 4

    h.remove_flag(B);
    h.print(); // should print 4
}

remove_flag()方法中有一个bug,它应该是flags |=i

但是,要这样做:

void remove_flag(flag f) { m_flags &= ~f; }
bool has_flag(flag f) { return !!(m_flags & f); }
void remove_flag(flag f) 
{
    m_flags &= ~f;
}

remove_flag()方法中有一个bug,它应该是flags |=i

但是,要这样做:

void remove_flag(flag f) { m_flags &= ~f; }
bool has_flag(flag f) { return !!(m_flags & f); }
void remove_flag(flag f) 
{
    m_flags &= ~f;
}
has_flag()和remove_flag()错误。它们应该是这样的:

void remove_flag(flag f) { m_flags &= ~f; }
bool has_flag(flag f) { return !!(m_flags & f); }
void remove_flag(flag f) 
{
    m_flags &= ~f;
}
has_flag()和remove_flag()错误。它们应该是这样的:

void remove_flag(flag f) { m_flags &= ~f; }
bool has_flag(flag f) { return !!(m_flags & f); }
void remove_flag(flag f) 
{
    m_flags &= ~f;
}

就我个人而言,我会使用std::vector来处理标志,因为它是一种将bool打包成位的专门化

然而:

我觉得你的删除标志有点复杂,试试这个

void remove_flag( flag f ) 
{
   if ( has_flag( f ) == true )
   {
      m_flags ^= f;   // toggle the bit leaving all other unchanged
   } 
}
编辑:
一条评论问我为什么不
做m_标志&=~f
。我认为这个问题是“学习者”问题,而不是优化问题。我展示了如何使他的代码正确,而不是快速。

我个人会使用std::vector来处理标志,因为它是一种将bool打包成位的专门化

然而:

我觉得你的删除标志有点复杂,试试这个

void remove_flag( flag f ) 
{
   if ( has_flag( f ) == true )
   {
      m_flags ^= f;   // toggle the bit leaving all other unchanged
   } 
}
编辑:
一条评论问我为什么不
做m_标志&=~f
。我认为这个问题是“学习者”问题,而不是优化问题。我展示了如何使他的代码正确,而不是快速。

每个人都已经明确了这一点:flag&=~f

has_flag():如果设置了f中的所有位,是否希望返回true?或者至少设置了其中一个?这是flags&f==f和flags&f之间的区别=0


你可以考虑包含和CUT< P>每个人都已经钉住这个:FLAG&= ~F;

has_flag():如果设置了f中的所有位,是否希望返回true?或者至少设置了其中一个?这是flags&f==f和flags&f之间的区别=0


你可能会考虑,如果没有事先检查,你就可以更快地删除一个标志,并且删除一个标志。我认为这是OP的一次学习经历,并简单地修改了他的代码以使其正常工作。我并没有纠正他的代码,使其更快。若f有超过1位的设置,而不是所有的设置在标志?flag&=~f解决了这个问题。flag是一个枚举,不能有多个值。如果std::vector有专门化,我怎么会看到这么多位字段仍在使用?如果不事先检查,擦除一个标志可能会更快(更简单)。你是对的。我认为这是OP的一次学习经历,并简单地修改了他的代码以使其正常工作。我并没有纠正他的代码,使其更快。若f有超过1位的设置,而不是所有的设置在标志?flag&=~f解决了这个问题。flag是一个枚举,不能有多个值。如果std::vector有专门化,我怎么会看到这么多位字段仍在使用?