Mam klasę enum z dwiema wartościami i chcę utworzyć metodę, która odbiera wartość i zwraca drugą. Chcę również zachować bezpieczeństwo typów (dlatego używam klasy wyliczeniowej zamiast wyliczeń).
http://www.cplusplus.com/doc/tutorial/other_data_types/ nie wspomina o metodach. Miałem jednak wrażenie, że każda klasa może mieć metody.
enum class/struct
?Odpowiedzi:
Nie, nie mogą.
Rozumiem, że
enum class
część dotycząca silnie wpisanych wyliczeń w C ++ 11 może wydawać się sugerować, że twoje teżenum
mająclass
cechy, ale tak nie jest. Zgaduję, że wybór słów kluczowych był inspirowany wzorcem, którego używaliśmy przed C ++ 11, aby uzyskać wyliczenia o określonym zakresie:Jednak to tylko składnia. Ponownie,
enum class
nie jestclass
.źródło
union
nie jest tym, co John Doe również uważałby za klasę . Jednak mogą pełnić funkcje członkowskie. A klasy tak naprawdę nie są obowiązkowe dla funkcji składowych. Używając desygnatora takiego jakvalue
lubthis
, coś podobnegoenum Size { Huge, Mega, Apocalypse; bool operator<(X rhs) const { return *this < rhs; }
(tutaj również pozwalającego;
), może to mieć taki sam sens, jak inne formy funkcji.Chociaż odpowiedź „nie możesz” jest technicznie poprawna, uważam, że możesz być w stanie osiągnąć pożądane zachowanie, korzystając z następującego pomysłu:
Wyobrażam sobie, że chcesz napisać coś takiego:
Miałeś nadzieję, że kod wygląda mniej więcej tak:
Ale oczywiście to nie działa, ponieważ wyliczenia nie mogą mieć metod (a „to” nic nie znaczy w powyższym kontekście)
Jeśli jednak zastosujesz ideę normalnej klasy zawierającej wyliczenie niebędące klasą i pojedynczą zmienną składową, która zawiera wartość tego typu, możesz bardzo zbliżyć się do wymaganej składni / zachowania / bezpieczeństwa typu. to znaczy:
Teraz możesz napisać:
Kompilator zapobiegnie takim sytuacjom, jak:
Możesz łatwo dodać takie metody, że:
i
mogą być obsługiwane.
źródło
Koncentrując się na opisie pytania zamiast na tytule, możliwa jest odpowiedź
źródło
Jak wspomniano w drugiej odpowiedzi , nie. Nawet
enum class
nie jest klasą.Zwykle potrzeba posiadania metod dla
enum
wyników wynika z tego, że nie jest to zwykłe (tylko zwiększające się) wyliczenie, ale rodzaj bitowej definicji wartości, które mają być maskowane lub wymagają innych operacji arytmetycznych:Oczywiście można pomyśleć o hermetyzowaniu operacji niezbędnych do ponownego ustawienia / ustawienia pojedynczych / grup bitów, np. Poprzez wartość maski bitowej lub nawet operacje sterowane indeksem bitowym, które byłyby przydatne do manipulowania takim zestawem „flag”.
Plik c ++ 11
struct
/class
specyfikacja obsługuje tylko lepsze określanie zakresu wartości wyliczenia w celu uzyskania dostępu. Nie więcej nie mniej!Sposobami na wyjście z tego ograniczenia, których nie można zadeklarować metod dla enum (klas), są użycie
std::bitset
(klasy opakowania) lub pola bitowegounion
.union
s, a takie związki bitfield mogą mieć metody (zobacz tutaj ograniczenia!).Mam próbkę, jak przekonwertować wartości maski bitowej (jak pokazano powyżej) na odpowiadające im indeksy bitowe, których można użyć
std::bitset
tutaj: BitIndexConverter.hppZnalazłem to bardzo przydatne do zwiększenia czytelności niektórych decyzji `` flag '' algorytmy.
źródło
Istnieje całkiem kompatybilna zdolność (§) do refaktoryzacji wyliczenia na klasę bez konieczności przepisywania kodu, co oznacza, że efektywnie możesz robić to, o co prosiłeś, bez zbytniej edycji.
(§) jak ElementW wskazuje w komentarzu, kod zależny od type_traits nie będzie działał, więc np. Nie można użyć auto, itp. Może być jakiś sposób na takie rzeczy, ale w końcu jest to konwersja wyliczenia na klasę, i zawsze błędem jest obalanie C ++
enum struct
ienum class
specyfikacje są o określenie zakresu, więc nie brać w tym udziału.Twoje oryginalne wyliczenie to np. „Zwierzak” (to jest tylko przykład!).
(1) Zmieniasz to na np. PetEnum (aby ukryć go przed istniejącym kodem).
(2) Dodajesz pod nią nową deklarację klasy (nazwaną oryginalnym wyliczeniem)
(3) Możesz teraz dodać dowolne metody klas do swojej klasy zwierząt domowych. na przykład. operator łańcuchowy
Teraz możesz użyć np. Std :: cout ...
źródło
pet
TypeName / instancji, czy to szablony,auto
lubdecltype
, psuje to, co dostajeszpetEnum
w zamian.Może nie spełnia wszystkich twoich potrzeb, ale z operatorami niebędącymi członkami nadal możesz się dobrze bawić. Na przykład:
Umożliwia to kod taki jak
źródło