Wpis z mikrobloga

Teraz dość filozoficzne pytanie z C++ i w ogóle programowania będzie.

Załóżmy, że chcę mieć funkcję, która wykonuje jedną z dwóch operacji w zależności od tego, który z dwóch teoretycznie przeciwstawnych warunków jest spełniony. Jeżeli żaden to niechybnie oznacza, że coś się #!$%@?ło, trzeba zakończyć program i zwrócić informację o błędzie. Napisałem:

void function() {

....if(coś) {

........operacja1();

....} else if(coś_innego) {

........operacja2();

....} else {

........std::unexpected();

....}

}

Kod dobrze spełnia swoje zadanie. Jeżeli coś jest nie tak to wywala się i wypisuje, że sterowanie zabrnęło tam, gdzie dojść nigdy nie powinno. Po poprawieniu błędów, w gotowym programie unexpected() nigdy się nie wykona. Na pewno tak jest sto razy lepiej niż zostawienie funkcji w ogóle bez else, bo wyskakują warningi, a po ominięciu if i else if mam naruszenie ochrony pamięci i nie jest jasne na pierwszy rzut oka gdzie.

Ale ładnie to tak? Może tak zostać, czy jest jakiś lepszy, ogólnie przyjęty sposób rozwiązywania problemów tego typu? Wydaje mi się jakieś takie brudne to rozwiązanie, zaciemniające kod. A zależy mi, żeby zrobić to porządnie. Propozycje?

#stylkodowania #programowanie #cpp
  • 17
@rss: Ciekawe. Dałem else, bo ta funkcja tak naprawdę nie jest void i chciałem uniknąć

warning: control reaches end of non-void function


ale okazało się, że nawet bez else to ostrzeżenie się nie pojawia. :)
@Onoki: Kompilator jest w stanie wydedukować (w określonych przypadkach), ƶe if/else if obsługuje wszystkie moƶliwe przypadki.

Przy okazji, nie lepiej rzucić wyjątkiem, niƶ wołać

std::unexpected
? (które jest, nota bene, deprecated)
@KrzaQ2: Rzucanie wyjątku jest chyba działaniem trochę na około, bo i tak nie mam zamiaru go łapać, a nieprzechwycony wyjątek wywołuje właśnie unexpected(). Dochodzą do tego problemy jakiego typu ma być wyjątek i dlaczego właśnie takiego. Tak zupełnie formalnie to powinienem stworzyć klasę #!$%@?łoSięException... Za dużo babrania.

@Ginden: Kompletnie nie rozumiem o co Ci chodzi.

Może rozwinę myśl: piszę grę, a funkcja funkcja przyjmuje obiekt, który w założeniu istnieje i
Kompletnie nie rozumiem o co Ci chodzi.


@Onoki: Pierwszy

if
wykonuje operację sprawdzenia, czy

a
i

b
po rzutowaniu na

bool
są sobie równe (wg twojego przykładu -

coś
i

coś_innego
). Jeśli tak - rzucasz wyjątkiem.

Jeśli są różne, to przechodzimy do bloku

else
. Najpierw sprawdzamy sobie warunek

a
(

coś
). Jeśli jest poprawny, to wykonujemy odpowiedni kod. Jeśli nie - znaczy, że warunek

b
musi być prawdziwy
@Ginden: No właśnie niestety nie. :( Teoretycznie obiekt przekazywany do funkcji powinien należeć do gracza A lub do gracza B. Praktycznie klasa tego obiektu ma konstruktor domyślny, który nie ustawia właściciela. I po to jest ten cały temat, że już raz mi się udało przekazać tej funkcji bezpański obiekt, w wyniku czego miałem naruszenie ochrony pamięci o niejasnym pochodzeniu i zmarnowałem kilkanaście minut na zlokalizowanie błędu. I po to jest ten
@Onoki: (#) No właśnie nie, po to jest pierwszy

if
- de facto sprawdza on, czy obiekt należy do któregoś z graczy (bo do tego sprowadzają się chyba warunki

coś
i

coś innego
, nieprawdaż?).
@Ginden: Ach tak, masz rację. Tylko, że otrzymuję dokładnie to samo (unexpected w miejscu Twojego komentarza // rzucasz błąd), a w dodatku przynależność do graczy jest sprawdzana trzy razy, a w mojej wersji jeden lub dwa.
@Onoki: (#) Czy sprawdzanie przynależności obiektu jest takie złożone obliczeniowo...?

PS. Ja bym się na Twoim miejscu zastanawiał, skąd się w ogóle biorą niczyje obiekty, bo prawdopodobnie masz gdzieś w logice aplikacji błąd.
Czy sprawdzanie przynależności obiektu jest takie złożone obliczeniowo...?


@Ginden: Nie, ale po co mam robić gorzej skoro mogę zrobić lepiej? :(

skąd się w ogóle biorą niczyje obiekty


Pracuję nad tym, ale na razie tak być musi. Jak w Heroes, masz stwory graczy i stwory neutralne. :D
Nie, ale po co mam robić gorzej skoro mogę zrobić lepiej? :(


@Onoki: Wiesz, czasem czytelność kodu jest ważniejsza niż dwa takty procesora... Można to oczywiście wrzucić do zmiennych pomocniczych i porównywać tylko wartości, żaden problem.
@Zbyszek223: To najgorsza rzecz jakiej uczą w szkołach. W ten sposób importujesz do głownej przestrzeni wszystko co jest w std o_O A tam przecież są bardzo generyczne nazwy:

sort, hex, distance, copy, move, fill, remove, min, max... nie sposób wymienić.