Utiliser des drapeaux binaires pour représenter des états, des options, etc.
Question
Si je souhaitais représenter des états ou des options ou quelque chose de similaire à l'aide de l'option binaire "drapeaux" afin que je puisse les transmettre et les stocker dans un objet tel que OPTION1 | OPTION2
où OPTION1
vaut 0001 et OPTION2
vaut 0010, de sorte que ce qui est passé est 0011, représentant un mélange d'options.
Comment ferais-je cela en C ++? Je pensais quelque chose comme
enum Option {
Option_1 = 0x01,
Option_2 = 0x02,
Option_3 = 0x04,
//...
}
void doSomething(Option options) {
//...
}
int main() {
doSomething(Option_1|Option_2);
}
Mais, dans l'idéal, quelque chose
sait comment interpréter l'option donnée.
Suis-je sur la bonne voie? Y a-t-il un meilleur moyen?
Mettre à jour
Et n’aurais-je pas besoin de définir une Option
pour chaque combinaison possible, également?
La solution
C’est une façon courante de faire ces choses. quelque chose
peut utiliser l'opérateur et
au niveau du bit pour voir si une option est sélectionnée:
if (options & Option_1){
// option 1 is selected
}
Vous pouvez également envisager d'utiliser les champs de bits :
struct Options {
unsigned char Option_1 : 1;
unsigned char Option_2 : 1;
};
Options o;
o.Option_1 = 1;
o.Option_2 = 0;
Autres conseils
Ce serait comme ça que je le ferais. Cependant, il existe de nombreuses astuces que vous pouvez utiliser pour rendre l'énumération un peu plus lisible:
enum Option {
Option1 = 1 /*<< 0*/,
Option2 = 1 << 1,
Option3 = 1 << 2,
// etc.
};
De plus, vous devrez spécifier des opérateurs au niveau des bits pour votre énumération. Pensez à quelque chose comme les utilitaires enum_ops
de l'ASL . / p>
Il est intéressant de noter que la façon dont les gens utilisent de tels drapeaux consiste à définir la fonction comme suit:
void doSomething( unsigned int options )
{
//...
}
tout le reste fonctionnera exactement comme vous le souhaitez:)
Vous pouvez également créer vos propres " drapeaux " classe. Ensuite, vous avez quelques fonctions comme suit dans la 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 même surcharger les opérateurs pour qu'ils fassent exactement ce que vous voulez, par exemple:
Flags( unsigned int options ) :
m_Option( options )
{
}
Flags operator|( const Flags& flags )
{
return Flags( m_Option | flags.m_Option );
}
et ainsi de suite.
Vous pouvez consulter le stl bitset . Certaines personnes prêcheraient que vous devriez toujours utiliser ceux-ci au lieu de bitflags de style C. Cependant, les deux solutions conviennent parfaitement à l’OMI.