Usando bandeiras binários para representar estados, opções, etc
Pergunta
Se eu quisesse representam estados ou opções ou algo semelhante usando "bandeiras" binários para que eu pudesse passá-los e armazená-los para um objeto como OPTION1 | OPTION2
onde OPTION1
é 0001 e OPTION2
é 0010, de modo que o que se passou é 0011, representando uma mistura das opções.
Como eu poderia fazer isso em C ++? Eu estava pensando em algo como
enum Option {
Option_1 = 0x01,
Option_2 = 0x02,
Option_3 = 0x04,
//...
}
void doSomething(Option options) {
//...
}
int main() {
doSomething(Option_1|Option_2);
}
Mas, em seguida, idealmente, doSomething
sabe como interpretar a opção dada.
Am I no caminho certo? Existe uma maneira melhor?
Atualizar
E eu não teria que definir uma Option
para cada combinação possível, também?
Solução
Esta é uma forma comum estas coisas são feitas. doSomething
pode usar o operador bit a bit and
para ver se uma opção for selecionada:
if (options & Option_1){
// option 1 is selected
}
Como alternativa, você pode considerar o uso campos de bits :
struct Options {
unsigned char Option_1 : 1;
unsigned char Option_2 : 1;
};
Options o;
o.Option_1 = 1;
o.Option_2 = 0;
Outras dicas
Isso seria a maneira que eu faria isso. No entanto, existem muitos truques que você pode usar para fazer a enumeração um pouco mais legível:
enum Option {
Option1 = 1 /*<< 0*/,
Option2 = 1 << 1,
Option3 = 1 << 2,
// etc.
};
O que é mais, você vai precisar especificar operadores bit a bit para sua enumeração. Considere algo como utilitários enum_ops
do ASL para ajudar com isso.
Sua digno que a forma como as pessoas costumam usar tais bandeiras é definir a função da seguinte forma:
void doSomething( unsigned int options )
{
//...
}
tudo o resto vai funcionar exatamente como você quiser:)
A outra maneira é criar seu próprio "Flags" classe. Então você tem um par de funções como segue na classe:
bool GetOption( Option option )
{
return (m_Option & option) > 0;
}
void SetOption( Option option )
{
m_Option |= option;
}
void ClearOption( Option option )
{
m_Option &= ~option;
}
ou até mesmo sobrecarregar os operadores para fazer exatamente como você gostaria por exemplo:
Flags( unsigned int options ) :
m_Option( options )
{
}
Flags operator|( const Flags& flags )
{
return Flags( m_Option | flags.m_Option );
}
e assim por diante.
Você pode querer verificar o stl bitset . Algumas pessoas pregam que você deve sempre usar aqueles em vez de bitflags de estilo C. No entanto, ambas as soluções são muito bem IMO.