Использование двоичных флагов для представления состояний, опций и т. Д

StackOverflow https://stackoverflow.com/questions/1407197

  •  05-07-2019
  •  | 
  •  

Вопрос

Если бы я хотел представить состояния или параметры или что-то подобное, используя двоичные "флаги", чтобы я мог передать их и сохранить в объекте типа OPTION1 | OPTION2 где OPTION1 является 0001 и OPTION2 является 0010, так что то, что передается, является 0011, представляющим сочетание параметров.

Как бы я сделал это на C ++?Я думал о чем-то вроде

enum Option {
    Option_1 = 0x01,
    Option_2 = 0x02,
    Option_3 = 0x04,
    //...
}

void doSomething(Option options) {
    //...
}

int main() {
    doSomething(Option_1|Option_2);
}

Но тогда в идеале, doSomething знает, как интерпретировать данный Вариант.

На правильном ли я пути?Есть ли способ получше?

Обновить

И разве мне не пришлось бы определить Option также для всех возможных комбинаций?

Это было полезно?

Решение

Это обычный способ, которым делаются подобные вещи. doSomething можно использовать побитово and оператор, чтобы узнать, выбрана ли та или иная опция:

if (options & Option_1){ 
  // option 1 is selected
}

В качестве альтернативы, вы можете рассмотреть возможность использования битовые поля:

struct Options {
    unsigned char Option_1 : 1;
    unsigned char Option_2 : 1;
};

Options o;
o.Option_1 = 1;
o.Option_2 = 0;

Другие советы

Именно так я бы это и сделал.Однако есть много приемов, которые вы можете использовать, чтобы сделать перечисление немного более читабельным:

enum Option {
    Option1 = 1 /*<< 0*/,
    Option2 = 1 << 1,
    Option3 = 1 << 2,
    // etc.
};

Более того, вам нужно будет указать побитовые операторы для вашего перечисления.Рассмотрим что-то вроде ASL's enum_ops утилиты, которые помогут с этим.

Стоит отметить, что люди обычно используют такие флаги, чтобы определить функцию следующим образом:

void doSomething( unsigned int options ) 
{
    //...
}

все остальное будет работать именно так, как вы хотите :)

Другой способ - создать свой собственный класс "Flags".Тогда у вас есть пара следующих функций в классе:

bool GetOption( Option option )
{
    return (m_Option & option) > 0;
}

void SetOption( Option option )
{
    m_Option |= option;
}

void ClearOption( Option option )
{
    m_Option &= ~option;
}

или даже перегрузите операторов, чтобы они делали именно то, что вы хотели бы, например:

Flags( unsigned int options ) :
   m_Option( options )
{
}

Flags operator|( const Flags& flags )
{
    return Flags( m_Option | flags.m_Option );
}

и так далее.

Возможно, вы захотите ознакомиться с набор битов stl.Некоторые люди проповедовали бы, что вы всегда должны использовать их вместо битовых флагов в стиле C.Тем не менее, оба решения хороши, IMO.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top