Typy wyliczeniowe - jaki jest sens?

0

Witam,uczę się C i zastanawiam się jaki sens jest używanie typów wyliczeniowych.

  1. Po pierwsze, zmienne tego typu są traktowane jak po prostu zwykłe zmienne całkowite i mogą mieć dowolną wartość, nawet z stałych wylieczeniowych.
  2. Po drugie, nawet zwykłem zmiennej całkowitej typu int mogę przypisać wartość za pomocą etykiety typu wyliczeniowego, np: enum kolory {czerwony,zielony,niebieski}; int liczba=czerwony;

Na wielu stronach jest napisane, że zmienne wylieczeniowe mogą przyjmować tylko wartości stałych wyliczeniowych, wtedy myślę byłby jakiś sens, albo gdyby te kolory mógłbym stosować do zmiennych tego typu, a nie do każdej zmiennej całkowitej.

0

Enumy są bardziej czytelne niż deklarowanie miliona intów, prostsze w debugowaniu niż #define'y (co mi po jakiejś liczbie, za którą muszę przejrzeć dokumentację i kilka plików, żeby się dowiedzieć co ona oznacza).

0

Ok, co do tego drugiego masz racje (z tym #define), ale co masz na myśli z tym milionem intów, przecież czy będziemy deklarować setki zmiennych typu enum czy typu int to i tak musimy je recznie te 100 razy zadeklarowac?

0

Podam ci Bracie matieti historyjkę z życia wziętą.

Otóż,dawniejszymi czasy razem z kumplem robiliśmy obsługę grafów czy czegoś w ten deseń.Do tworzenia węzłów używaliśmy funkcji z około 7 parametrami typu bool.Wyglądało to mniej więcej tak:

utwórz(true,false,false,false,true,false,false);
utwórz(false,true,false,true,true,false,false);
utwórz(true,false,true,true,false,false,true);
utwórz(false,true,false,true,false,true,false);

szybko zaliczylismy WTF podczas patrzenia na taki kod,i boole zastąpiliśmy różnakimi enumami,które miały jakieś dorzeczne nazwy.Wywołanie przy pomocy enumów wyglądało bodajże tak:

utwórz(IsNotRoot,IsChild,LeftChildExist,RightChildNotExist,2 ostatnie już nie kojarzę);

I teraz sam oceń,który kod jest czytelniejszy? :]

0

Ale wartości są nadawane z automatu, a wszystkie stałe w jakiś sposób powiązane ze sobą możemy wrzucić w jednego enuma i mamy z tego nowy typ.
Więc możemy zrobić:

void setKolor(Kolor kolor) {
}

zamiast nic niemówiącego inta (skąd mamy brać wartości? jakie są dozwolone?). Enumy są po prostu czytelniejsze.
W dodatku, chociaż konwersja enum -> int jest ok, to na odwrót, chociaż też możliwa, jest unsafe i nie może być niejawna:

setKolor(czerwony); // ok
setKolor(0); // błąd
setKolor(Kolor(0)); // wiem co robię, ale po co tak?

Ok, pytanie było o C, a tam enumy są bardziej krzywe. W takim razie druga połowa postu tyczy się tylko C++

0

wyobraź sobie, że piszesz biblioteke do obsługi sieci bez enum:

#define XXX 0x00
#define XXY 0x01
...
#define ZZZ 0xFF

i jak się piierdolniesz w numeracji i założysz, że na pewno nie zrobiłeś tam błędu to potem będziesz długimi godzinami szukać błędu

0
MasterBLB napisał(a)
utwórz(IsNotRoot,IsChild,LeftChildExist,RightChildNotExist,2 ostatnie już nie kojarzę);

I teraz sam oceń,który kod jest czytelniejszy? :]

Taki: :)

enum
{
    IsNotRoot  = 1,
    IsChild = 2,
    RightChildNotExist = 4
    // etc..
};

utwórz(IsNotRoot + IsChild);
utwórz(RightChildNotExist);

// czyli 
void utworz(uint maska);

Tak robię jak mam kilka flag bool, ale gdy jest masa nie-bool parametrów, to już wolę obiekt-parametr:

void utworz(const ZestawParametrow &parms);

class ZestawParametrow {
public:
  ZestawParametrow() {
    // ustaw wartosci domyslne
  }
 
  void setIsNotRoot(bool value);
  void setIsChild(bool value);
  // etc.
};

// A potem użycie:
ZestawParametrow zestaw;
zestaw.setIsNotRoot(true);
zestaw.setIsChild(true);
utworz(zestaw);

Długa lista parametrów jest w każdym wypadku do (negatywny zwrot)...

0
vpiotr napisał(a)

Tak robię jak mam kilka flag bool, ale gdy jest masa nie-bool parametrów, to już wolę obiekt-parametr:

void utworz(const ZestawParametrow &parms);

class ZestawParametrow {
public:
  ZestawParametrow() {
    // ustaw wartosci domyslne
  }
 
  void setIsNotRoot(bool value);
  void setIsChild(bool value);
  // etc.
};

// A potem użycie:
ZestawParametrow zestaw;
zestaw.setIsNotRoot(true);
zestaw.setIsChild(true);
utworz(zestaw);

Długa lista parametrów jest w każdym wypadku do (negatywny zwrot)...

Ostatnio gdzieś wyczytałem by właśnie pakować w struktury skomplikowane parametry funkcji. Też to zacząłem używać i muszę przyznać że upraszcza to kod, a jeśli jest potrzeba dodania parametru to rozbudowuje się strukturę. Tutaj jednak bym optował przy strukturach a nie klasach. Deklarujesz strukturę pomocniczą ze składowymi typu const i dodajesz konstruktor przyjmujący te parametry i jest ok jak na mój gust. Choć w sumie jeśli chodzi o parametry typu bool to klasa chyba użyteczniejsza niż struktura, ale struktura, która ma trzymać konkretne wartości jest lepsza niż kasa(uff zamotałem ale mam nadzieję że da się to zrozumieć).

0
IsNotRoot + IsChild

Czemu '+'? Bitowe OR by tutaj raczej bardziej pasowało.

I jeszcze taka uwaga - nazwy typu IsNotRoot mają tendencję do powodowania wtf-ów, lepiej by było po prostu IsRoot.

0

@Hostel & vpiotr
Mówicie,żeby pakować do struktur większość ilość parametrów funkcji-cóż,zapraszam zatem do zapoznania się z WinAPI i takim fundamentalnym zagadnieniem,jakim jest tworzenie nowego okna w tejże technologii :]

Co do samej zasady,ja tam jestem zwolennikiem KISSa i brzytwy Ockhama-jak najmniej wszystkiego,jak najprostsze,póki absolutnie nie muszę nie wprowadzam nowych klas.

Co do samego przykładu,to było to już tak dawno że za Swaroga sobie nie przypomnę,czemu akurat funkcja z 7 boolami była potrzebna.

1 użytkowników online, w tym zalogowanych: 0, gości: 1