Załóżmy, że mamy enum
podobne:
enum Days {Saturday, Sunday, Tuesday, Wednesday, Thursday, Friday};
Chcę utworzyć instancję tego enum
i zainicjować ją z odpowiednią wartością, więc:
Days day = Days.Saturday;
Teraz chcę sprawdzić moją zmienną lub instancję z istniejącą enum
wartością, więc:
if (day == Days.Saturday)
{
std::cout << "Ok its Saturday";
}
Co daje mi błąd kompilacji:
błąd: oczekiwane wyrażenie podstawowe przed „.” znak
Żeby było jasne, jaka jest różnica między powiedzeniem:
if (day == Days.Saturday) // Causes compilation error
i
if (day == Saturday)
?
Co tak naprawdę odnoszą się do tych dwóch, że jest OK, a drugi powoduje błąd kompilacji?
Odpowiedzi:
Ten kod jest nieprawidłowy:
Ponieważ
Days
nie jest zakresem ani przedmiotem. To jest typ. A same typy nie mają członków. To, co napisałeś, jest odpowiednikiemstd::string.clear
.std::string
jest typem, więc nie możesz go używać.
. Używasz.
na instancji klasy.Niestety wyliczenia są magiczne, więc analogia się tam kończy. Ponieważ w przypadku klasy można
std::string::clear
uzyskać wskaźnik do funkcji składowej, ale w C ++ 03Days::Sunday
jest niepoprawny. (Co jest smutne). Wynika to z tego, że C ++ jest (nieco) wstecznie kompatybilny z C, a C nie ma przestrzeni nazw, więc wyliczenia musiały znajdować się w globalnej przestrzeni nazw. Więc składnia jest po prostu:Na szczęście Mike Seymour zauważa, że zostało to rozwiązane w C ++ 11. Zmień
enum
sięenum class
i uzyska swój zakres;Days::Sunday
jest więc nie tylko poprawny, ale jest jedynym sposobem na dostępSunday
. Szczęśliwe dni!źródło
enum
sięenum class
i uzyska swój zakres;Days::Sunday
jest więc nie tylko poprawny, ale jest jedynym sposobem na dostępSunday
. Szczęśliwe dni!'.' token
idot operator
, poza tym, że jest to token, a nie operator, i pokazuje dokładny symbol, a nie nazwę.enum
, nie możesz użyć zakresu ani globalnego zakresu (::Saturday
). Jeśli maszenum class
(co jest bardzo inna sprawa), to mają do użytkuDays::Saturday
.To wystarczy, aby zadeklarować zmienną enum i porównać ją:
źródło
Days
nie jest zakresem ani przedmiotem. To jest typ. A same typy nie mają członków.std::string.clear
również nie kompiluje się z tego samego powodu.enum class
, nowe w 2011 roku) posiada swój własny zakres i są dostępne za pomocą operatora zakresu,Days::Saturday
. Operator dostępu do elementu (.
) służy wyłącznie do uzyskiwania dostępu do elementów klasy.Znaczna część tego powinna dać błędy kompilacji.
Teraz
Saturday
,Sunday
itp mogą być stosowane jako najwyższego poziomu gołymi stałych iDays
może być używany jako typ:I podobnie później, aby przetestować:
Te
enum
wartości są jak gołymi stałych - Są un -scoped - przy odrobinie pomocy ze strony kompilatora: (chyba, że używasz C ++ 11 klas enum ) oni nie są zamknięte jak przedmiot lub członków struktury, na przykład, i Państwo nie może odnosić się do nich jako członków oDays
.Będziesz mieć to, czego szukasz z C ++ 11 , który wprowadza
enum class
:Zauważ, że ten C ++ różni się nieco od C na kilka sposobów, jeden jest taki, że C wymaga użycia
enum
słowa kluczowego podczas deklarowania zmiennej:źródło
Możesz użyć sztuczki, aby używać zakresów według własnego uznania, po prostu zadeklaruj enum w następujący sposób:
źródło
Zamiast używać szeregu instrukcji if, wyliczenia nadają się dobrze do przełączania instrukcji
Używam niektórych kombinacji wyliczania / przełączania w konstruktorze poziomów, który buduję dla mojej gry.
EDYCJA: Kolejna rzecz, widzę, że chcesz składnię podobną do;
Możesz to zrobić w C ++:
Oto bardzo prosty przykład:
EnumAppState.h
Somefile.cpp
źródło
Jeśli nadal używasz C ++ 03 i chcesz używać wyliczeń, powinieneś używać wyliczeń wewnątrz przestrzeni nazw. Na przykład:
Możesz użyć wyliczenia poza przestrzenią nazw, np.
źródło
Szukasz silnie typowanych wyliczeń , funkcja dostępna w standardzie C ++ 11 . Zamienia wyliczenia w klasy o wartościach zasięgu.
Korzystając z własnego kodu przykład:
Użycie
::
jako akcesorium do wyliczeń zakończy się niepowodzeniem, jeśli będzie się celować w standard C ++ wcześniejszy niż C ++ 11. Ale niektóre stare kompilatory go nie obsługują, a niektóre IDE po prostu zastępują tę opcję i ustawiają stary standard C ++.Jeśli używasz GCC, włącz C + 11 za pomocą -std = c ++ 11 lub -std = gnu11 .
Bądź szczęśliwy!
źródło
enum class Days { ...
.To nie powinno działać w C ++:
Dni nie jest zakresem ani obiektem zawierającym członków, do których można uzyskać dostęp za pomocą operatora kropki. Ta składnia jest tylko językiem C # i nie jest legalna w C ++.
Microsoft od dawna utrzymuje rozszerzenie C ++, które umożliwia dostęp do identyfikatorów za pomocą operatora zasięgu:
Ale jest to niestandardowe przed C ++ 11. W C ++ 03 identyfikatory zadeklarowane w wyliczeniu istnieją tylko w tym samym zakresie, co sam typ wyliczenia.
C ++ 11 zezwala na kwalifikowanie identyfikatorów enum za pomocą nazwy enum, a także wprowadza klasy enum, które tworzą nowy zakres dla identyfikatorów zamiast umieszczać je w otaczającym zakresie.
źródło
Niestety elementy wyliczenia są „globalne”. Masz do nich dostęp, robiąc
day = Saturday
. Oznacza to, że nie możesz miećenum A { a, b } ;
ienum B { b, a } ;
są w konflikcie.źródło
enum class
To znaczy, dopóki nie użyjesz w C ++ 11. Wcześniej musisz robić zajęcia pozorowane.Podczas gdy C ++ (z wyjątkiem C ++ 11) ma wyliczenia, ich wartości są „wyciekane” do globalnej przestrzeni nazw.
Jeśli nie chcesz, aby wyciekły (i NIE POTRZEBUJESZ użyć typu wyliczeniowego), rozważ następujące kwestie:
źródło
Wyliczenia w C ++ są jak liczby całkowite zamaskowane nazwami, które im podajesz, kiedy deklarujesz swoje wartości wyliczeniowe (nie jest to definicja, tylko wskazówka, jak to działa).
Ale w twoim kodzie są dwa błędy:
enum
wszystkie małe literyDays.
przed sobotą.if (day == YourClass::Saturday){}
źródło
Myślę, że twoim głównym problemem jest użycie
.
zamiast::
, który użyje przestrzeni nazw.Próbować:
źródło
Days::
zakresu jak w twoim przykładzie, musisz zdefiniować wyliczenie zaenum class Days
pomocą rozszerzenia C ++ 03 + Microsoft lub C ++ 11.-std=c++98
lub-std=c++03
. Clang jest dość oczywiste:warning: use of enumeration in a nested name specifier is a C++11 extension
.Jeśli chcemy ścisłego bezpieczeństwa typu i wyliczania zakresu, używanie
enum class
jest dobre w C ++ 11.Gdybyśmy musieli pracować w C ++ 98, moglibyśmy skorzystać z porady udzielonej przez
InitializeSahib
,San
aby włączyć wyliczanie zakresu.Jeśli chcemy również ścisłego bezpieczeństwa typu, poniższy kod może zaimplementować coś takiego
enum
.Kod został zmodyfikowany na podstawie przykładu klasy miesiąc w książce Effective C ++ 3rd: Item 18
źródło
Przede wszystkim wpisz „E” in enum, „e” jako małą literę.
Po drugie, w polu „Days.Saturday” wpisz nazwę „Days”.
Po trzecie ... kup sobie dobrą książkę C ++.
źródło