Utilizzo di flag binari per rappresentare stati, opzioni, ecc
Domanda
Se volessi rappresentare stati o opzioni o qualcosa di simile usando i binari "flag" in modo da poterli passare e archiviarli in un oggetto come OPTION1 | OPTION2
dove OPTION1
è 0001 e OPTION2
è 0010, quindi ciò che viene superato è 0011, che rappresenta un mix di opzioni.
Come lo farei in C ++? Stavo pensando a qualcosa del genere
enum Option {
Option_1 = 0x01,
Option_2 = 0x02,
Option_3 = 0x04,
//...
}
void doSomething(Option options) {
//...
}
int main() {
doSomething(Option_1|Option_2);
}
Ma idealmente, doSomething
sa come interpretare l'opzione data.
Sono sulla buona strada? Esiste un modo migliore?
Aggiorna
E non dovrei definire un'opzione
anche per ogni possibile combinazione?
Soluzione
Questo è un modo comune di fare queste cose. doSomething
può utilizzare l'operatore bitcode e
per vedere se un'opzione è selezionata:
if (options & Option_1){
// option 1 is selected
}
In alternativa, puoi prendere in considerazione l'utilizzo di campi di bit :
struct Options {
unsigned char Option_1 : 1;
unsigned char Option_2 : 1;
};
Options o;
o.Option_1 = 1;
o.Option_2 = 0;
Altri suggerimenti
Sarebbe il modo in cui lo farei. Tuttavia ci sono molti trucchi che puoi usare per rendere l'enumerazione un po 'più leggibile:
enum Option {
Option1 = 1 /*<< 0*/,
Option2 = 1 << 1,
Option3 = 1 << 2,
// etc.
};
Inoltre, dovrai specificare operatori bit a bit per la tua enumerazione. Prendi in considerazione qualcosa come le utility enum_ops
di ASL per aiutarti in questo.
Vale la pena notare che il modo in cui le persone usano tali flag è definire la funzione come segue:
void doSomething( unsigned int options )
{
//...
}
tutto il resto funzionerà esattamente come vuoi :)
L'altro modo è creare le tue " Bandiere " classe. Quindi hai un paio di funzioni come segue nella classe:
bool GetOption( Option option )
{
return (m_Option & option) > 0;
}
void SetOption( Option option )
{
m_Option |= option;
}
void ClearOption( Option option )
{
m_Option &= ~option;
}
o addirittura sovraccaricare gli operatori per fare esattamente come desideri, ad esempio:
Flags( unsigned int options ) :
m_Option( options )
{
}
Flags operator|( const Flags& flags )
{
return Flags( m_Option | flags.m_Option );
}
e così via.
Puoi dare un'occhiata al stl bitset . Alcune persone predicano che dovresti sempre usare quelli invece dei bitflags in stile C. Tuttavia, entrambe le soluzioni vanno bene IMO.