C ++ настраивает «флаги» - PullRequest
       15

C ++ настраивает «флаги»

2 голосов
/ 04 апреля 2010

Пример:

enum Flags
{
    A,
    B,
    C,
    D
};

class MyClass
{
   std::string data;
   int foo;

   // Flags theFlags; (???)
}
  • Как добиться того, чтобы можно было установить любое количество «флагов» A, B, C и D в перечислении выше в экземпляре MyClass?

Моя цель будет выглядеть примерно так:

if ( MyClassInst.IsFlagSet( A ) ) // ...
MyClassInst.SetFlag( A ); //...
  • Нужно ли использовать какой-нибудь массив или вектор?Если да, то как?
  • Являются ли перечисления хорошей идеей в этом случае?

Ответы [ 4 ]

3 голосов
/ 04 апреля 2010
// Warning, brain-compiled code ahead!

const int A = 1;
const int B = A << 1;
const int C = B << 1;
const int D = C << 1;

class MyClass {
public:
  bool IsFlagSet(Flags flag) const {return 0 != (theFlags & flag);}
  void SetFlag(Flags flag)         {theFlags |= flag;}
  void UnsetFlag(Flags flag)       {theFlags &= ~flag;}

private:
   int theFlags;
}
2 голосов
/ 04 апреля 2010

В C вы устанавливаете специальные (непоследовательные) значения перечисления вручную:

enum Flags
{
    A = 1,
    B = 2,
    C = 4,
    D = 8
};

Лучше использовать безопасность типов:

const int A = 1;
const int B = 2; /* ... */

, потому что (A | B)не является одним из значений перечисления.

0 голосов
/ 04 апреля 2010

Если foo - ваш битовый флаг, вы можете установить A на foo, выполнив:

foo |= A

Сбросьте A на foo, выполнив:

foo &= (~A)

И проверьте, установлен ли A на foo, проверив, истинно ли это выражение

(foo & A) == A

Но вам нужно убедиться, что значения A, B, C, D установлены правильно (0x01, 0x02, ...)

0 голосов
/ 04 апреля 2010

Нет, вам не нужно использовать массив или вектор, но вам нужно побитовое сравнение.

Первый шаг - установить для числового значения каждого флага экспоненциальное значение 2 (например, 1,2,4,8,16,32,64 и т. Д.), Поэтому в двоичномбудет выглядеть как 0001,0010,0100,1000 и т. д.

Теперь, чтобы установить или удалить флаг, вам нужно либо добавить его в переменную Flag, либо удалить его.Пример проверки на флаги будет выглядеть так:

if(MyClass.Flags & FLAG_A)
{
    // Flag is set
}

if(!(MyClass.Flags & FLAG_B))
{
    // Flag is not set
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...