2009-12-09 14 views
6

Niedawno natknąłem niektórych funkcji, gdzie można przekazać wiele stałe teksty tak:C++ wielokrotne wyliczenia w jednym argumencie funkcji za pomocą bitowej lub "|"

myFunction(One | Two); 

Ponieważ myślę, że to jest naprawdę elegancki sposób starałem się wdrożyć coś takiego sobie:

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

teraz jeśli spróbuję wywołać funkcję z One | Po drugie, chcę, żeby zadzwoniono do obu skrzynek z przełącznikami. Nie jestem dobry z operatorami binarnymi, więc naprawdę nie wiem co robić. Wszelkie pomysły byłyby świetne!

Dzięki!

+1

Opublikuj swoją definicję "enum". Czy pamiętasz, aby zrobić z nich wszystkie moce 2? – eduffy

+1

Uwaga: nazwa _a jest zarezerwowana dla implementacji C++, chyba że jest to nazwa członka klasy. –

Odpowiedz

11

Do tego trzeba dokonać stałe teksty typu:

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

tj enum wartość element powinien być w sile 2, aby wybrać ważne sprawy lub jeśli oświadczenie.

Więc jeśli lubisz:

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

Jeszcze lepiej, użyj 'wylicz STATE {STATE_A = 1 << 0, STATE_B = 1 << 1, STATE_C = 1 << 2};' - Uważam, że o wiele bardziej wyraźne. – DevSolar

+3

Nie byłyby to stany przy okazji. Państwa mają być wyłączne. Bardziej prawdopodobne są flagi (gdzie poszczególne flagi są niezależne od siebie). – paxdiablo

+0

dziękuję, zrobiłem to tak, jak sugerowaliście i działa! – moka

2

Musisz podzielić możliwe „znaków” (bez nakładania się oczywiście ... wykorzystać moc 2):

if (_a & One) { ... } 

Nie elegancki naprawdę robić, co chcesz z oświadczeniem 1 przełącznik split użyciu if sprawozdań .

2

Jesteś lepiej to robić z zestawem instrukcji if ...

tj

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

EDIT: Można również zrobić to w instrukcji switch, ale byłby to koszmar. Potrzebujesz czegoś takiego, jak to

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

case TWO: 
    // Handle TWO. 
    break; 

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

Jest względnie rozsądny tylko z 2 opcjami, ale gdy dostaniesz więcej, zaczyna tracić kontrolę. Jeśli masz 32 opcje, możesz mieć instrukcję zmiany, która nie pasowałaby do żadnej maszyny. Wszystko w rozwiązaniu "jeśli" jest dużo czystsze i bardziej rozsądne :)

+0

dziękuję, masz rację, używam instrukcji if teraz i działa jak urok! – moka

3

Zazwyczaj argumenty, które są połączone w ten sposób, to flagi (wartość z pojedynczym zestawem bitów) z wartością dziesiętną równą 1, 2, 4, 8 itd. Zakładając, że Jeden i Dwa przestrzegają tej zasady, nie możesz użyć przełącznika, aby sprawdzić oba. Przełączniki podążają tylko jedną ścieżką. Twój połączony argument nie jest równy One lub Two, ale ich kombinacja (1 | 2 == 3). Można sprawdzić, czy jeden lub dwa jest ustawiony tak:

if (_a & One) 
{ 

} 
if (_a & Two) 
{ 

} 

Pamiętaj, że standardowy enum bez wyraźnych wartości będzie po prostu policzyć w górę, nie używać następny kawałek. Jeśli twoja następna zdefiniowana wartość to Three, prawdopodobnie będzie równa 3, która nie jest wartością pojedynczego bitu, a następnie będzie działać tak, jakbyś przekazała obie funkcje (One | Two). Musisz samodzielnie ustawić wartości wyliczenia.

8

operatory bitowe zachowują się dobrze tylko z uprawnieniami 2:

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


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

Jeśli spróbujesz zrobić to samo z dowolnych liczb, dostaniesz nieoczekiwane wyników:

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

Który zawiera możliwe (dowolne) liczby jak ustawione flagi: 0001 (1), 0100 (4), 0101 (5), 1000 (8) 1001 (9), 1100 (12), 1101 (13)

Więc zamiast dać dwie opcje, po prostu dał sześć.