2009-12-09 16 views
6

ich auf einige Funktionen vor kurzem kam, wo Sie mehrere Aufzählungen wie dies passieren kann: jetztC++ mehrere Enums in einem Funktionsargument mit bitweisem oder "|"

void myFunction(int _a){ 
    switch(_a){ 
     case One: 
      cout<<"!!!!"<<endl; 
      break; 
     case Two: 
      cout<<"?????"<<endl; 
      break; 
    } 
} 

:

myFunction(One | Two); 

Da ich denke, das ist eine wirklich elegante Art und Weise habe ich versucht zu implementieren so etwas selbst wenn ich versuche, die Funktion mit One | aufzurufen Zweitens möchte ich, dass beide Switch-Fälle angerufen werden. Ich bin nicht wirklich gut mit binären Operatoren, also weiß ich nicht wirklich, was ich tun soll. Irgendwelche Ideen wären großartig!

Danke!

+1

Poste deine 'enum'-Definition .. hast du daran gedacht, sie alle 2er zu machen? – eduffy

+1

Beachten Sie, dass der Name _a für die C++ - Implementierung reserviert ist, es sei denn, es handelt sich um den Namen eines Klassenmembers. –

Antwort

11

Dafür Sie machen müssen, um Aufzählungen wie:

enum STATE { 
    STATE_A = 1, 
    STATE_B = 2, 
    STATE_C = 4 
}; 

heißt Enum Elementwert in Potenz von 2 sein sollte, gilt Fall oder wenn Aussage auszuwählen.

Also, wenn Sie tun:

void foo(int state) { 

    if (state & STATE_A) { 
    // do something 
    } 

    if (state & STATE_B) { 
    // do something 
    } 

    if (state & STATE_C) { 
    // do something 
    } 
} 

int main() { 
    foo(STATE_A | STATE_B | STATE_C); 
} 
+8

Noch besser, verwenden Sie 'enum STATE {STATE_A = 1 << 0, STATE_B = 1 << 1, STATE_C = 1 << 2};' - Ich finde das viel expliziter. – DevSolar

+3

Sie wären übrigens keine Zustände. Staaten sollen exklusiv sein. Sie sind eher Flaggen (wo die einzelnen Flaggen unabhängig voneinander sind). – paxdiablo

+0

danke, ich tat es wie ihr vorgeschlagen habt und es funktioniert! – moka

2

Sie müssen den möglichen "Token" aufgeteilt (nicht-überlappende natürlich ... Potenz von 2 verwenden):

if (_a & One) { ... } 

elegant Nicht wirklich tun, was Sie mit 1 Switch-Anweisung wollen: split mit if Aussagen .

2

Sie sind besser dran, es mit einer Reihe von if-Anweisungen zu tun ...

dh

if (_a & ONE) 
{ 
    // Do stuff. 
} 
if (_a & TWO) 
{ 
    // Do other stuff. 
} 

bearbeiten: Sie können auch in einer switch-Anweisung tun, aber es wäre ein Albtraum. Youd braucht so etwas wie dieses

switch(_a) 
{ 
case ONE: 
    // Handle ONE. 
    break; 

case TWO: 
    // Handle TWO. 
    break; 

case ONE | TWO: 
    // Handle ONE. 
    // Handle TWO. 
    break; 
}; 

Sein relativ gesund für nur zwei Optionen, aber sobald man sich mehr, als dass es beginnt die Kontrolle Ballon aus. Wenn Sie 32-Optionen haben, würden Sie eine switch-Anweisung haben, die wahrscheinlich nicht auf irgendeinen Computer passen würde. Alles in der "if" -Lösung ist viel sauberer und viel vernünftiger :)

+0

danke, du hast Recht, ich benutze wenn jetzt Aussagen und es funktioniert wie ein Charme! – moka

3

Gewöhnlich Argumente, die auf diese Weise kombiniert werden, sind Flags (ein Wert mit einem einzelnen Bit gesetzt) ​​mit einem Dezimalwert von 1, 2, 4, 8 usw. Unter der Annahme, dass Eins und Zwei dieser Regel folgen, können Sie keinen Schalter verwenden, um nach beiden zu suchen. Switches folgen nur einem Pfad. Ihr kombiniertes Argument ist nicht gleich Eins oder Zwei, sondern eine Kombination davon (1 | 2 == 3). Sie können überprüfen, ob ein oder zwei wie folgt festgelegt ist:

if (_a & One) 
{ 

} 
if (_a & Two) 
{ 

} 

Denken Sie daran, dass eine Standard-Enumeration ohne explizite Werte nur aufwärts zählt, nicht das nächste Bit verwenden. Wenn Ihr nächster definierter Wert Three ist, wird er wahrscheinlich gleich 3 sein, was kein Wert eines einzelnen Bits ist, und wird dann so tun, als ob Sie beide Flags (One | Two) an die Funktion übergeben hätten. Sie müssen die Werte des Enums selbst festlegen.

8

Bit-Operatoren verhalten sich auch nur mit Potenzen von 2:

0010 
| 0100 
------ 
    0110 // both bits are set 


    0110 
& 0100 
------ 
    0100 // nonzero, i.e. true: the flag is set 

Wenn Sie versuchen, das gleiche mit beliebigen Zahlen zu tun, werden Sie unerwartete bekommen Ergebnisse:

0101 // 5 
| 1100 // 12 
------ 
    1101 // 13 

Die enthält die möglichen (willkürlichen) Zahlen als gesetzt Flags: 0001 (1), 0100 (4), 0101 (5), 1000 (8), 1001 (9), 1100 (12), 1101 (13)

Anstatt also zwei Möglichkeiten geben, Sie gab nur sechs.