2010-11-05 6 views
5

Czy byłyby jakieś różnice Jeśli zrobię co następuje bez wyjątków?Kiedy łapać wyjątki?

void func() 
{ 
    try 
    { 
     if (n > 5) 
     { 
      throw "n is greater than 5"; 
     } 
    } 
    catch (const char *e) 
    { 
     MessageBox(0, e, 0, 0); 
     return; 
    } 
} 

LUB

void func() 
{ 
    if (n > 5) 
    { 
     MessageBox(0, "n is greater than 5", "Error", 0); 
     return; 
    } 
} 
+1

zostaniesz przeniesiony do kosza, aby rzucić "char const *" w pierwszym przypadku. –

+0

Może być różnicą w tytule "Błąd" i inżynierią wsteczną kodu. . . – k06a

Odpowiedz

8

Prawdopodobnie powiedziałbym, że najlepiej nie używać wyjątków do kontroli przepływu. Wyjątki, jak sama nazwa wskazuje, dotyczą wyjątkowych okoliczności. W powyższym przypadku najwyraźniej spodziewasz się, że prawdopodobnie będzie> 5, więc nie jest to wyjątkowa okoliczność. Jeśli istnieje sposób, aby Twoja aplikacja mogła poradzić sobie z tą sprawą, powinna to zrobić, zamiast zgłaszać wyjątek.

Jestem pewien, że są przypadki, w których ta logika spada, ale generalnie uważam, że jest to dobra zasada.

Jednak z technicznego punktu widzenia nie ma dużej różnicy (prawdopodobnie wydajność, jeśli robisz to dużo).

0

Nie ma istotnej różnicy w swoim przykładzie (oprócz oczywistego faktu, że jeden używa wyjątki, a drugi nie!) - to byłoby rozsądne refaktoryzacji. Jeśli jednak istnieje wiele różnych błędów, może się okazać, że wzór throw... catch pomaga utrzymać obsługę błędów w jednym miejscu.

2

Wynik końcowy byłby dokładnie tym samym, to jest na pewno.

Powinieneś spróbować uprościć wszystko w kodzie, tak bardzo jak to możliwe, więc bardzo zniechęcam do używania wyjątku w tym przypadku.

0

W twoim przykładzie nie ma różnicy. Jedyną rzeczą, którą musisz wymyślić, jest to, że gdy zostanie zgłoszony wyjątek, pozostałe instrukcje stwierdzą, że próba ... metoda catch nigdy nie zostanie wykonana. Exceptions są zasadniczo używane do obsługi "specjalnych warunków, które zmieniają normalny przepływ wykonywania programu." (Twój jest po prostu podstawowym, normalnym logicznym błędem przepływu).

Mam nadzieję, że to pomoże.

0
void func() 
{ 
    if (n > 5) 
    { 
     MessageBox(0, "n is greater than 5", "Error", 0); 
     return; 
    } 
} 

Nie wyrzucaj wyjątku samemu, jeśli możesz sobie z tym poradzić samodzielnie, sprawdzając powyższy kod, To nie jest dobra praktyka.

2

Bardzo trudno dokładnie określić, kiedy powinny być stosowane wyjątki. W niektórych przypadkach wyjątek jest oczywistym zwycięzcą, aw innych przypadkach nie.

Zasadnicze pytanie brzmi: skąd pochodzi n i czy może być, w normalnych okolicznościach, wartością> 5. Jeśli n jest obliczane przez samą funkcję i zwykle może mieć tę wartość, to wyjątek nie czuć się dobrze. Jeśli jednak n jest podane gdzie indziej, a ta funkcja po prostu nie oczekuje wysokiej wartości, wówczas wyjątek wydaje się bardziej poprawny.

Jednak twój przykład powiedziałbym, że złe korzystanie z wyjątków. Rzucanie i łapanie wyjątków w ramach tej samej funkcji prawie zawsze jest złą formą. Jest to standardowa kontrola przepływu. Wyjątki powinny być stosowane, gdy warunek błędu musi być propagowany poza funkcją.

3

Nigdy nie wyrzucaj wyjątku, który następnie przechwycisz w tej samej funkcji. Jest to znak, że używasz wyjątków dla standardowego przepływu sterowania, co lepiej zrobić z/if/break/etc.

+1

Nigdy nie mów nigdy! :-) –

+0

@Alf: zazwyczaj nigdy nie powinieneś mówić nigdy. To jedyny wyjątek! :) –

+0

OK, to jeden wyjątek od wyjątku do reguły dotyczącej rzucania i przechwytywania wyjątku w tej samej funkcji opartej na wyjątkach, to kiedy emulujesz wyjątek podobny do Javy 'finally' w C++. Chociaż RAII będzie na ogół bardziej czysty, zgaduję, że może istnieć jakiś wyjątek? Twoje zdrowie, –

0

Nie zdefiniowałeś n.

z następującą definicją n nie różni się zaobserwować zachowanie.

struct Silly 
{ 
    ~Silly() { cout << "Hm de dum" << endl; } 
    operator bool() const { return true; } 
}; 

struct SillyProducer 
{ 
    Silly operator>(int) const { return Silly(); } 
}; 

#define n Silly silly = SillyProducer() 

Cheers & HTH,

0

Wiele już zostało powiedziane, ja po prostu dodać coś z mojej strony.

W twoim przypadku oba przypadki są poprawne, z wyjątkiem tego, że zachęcam do podzielenia tego na dwie warstwy: logikę i widok. Więc warstwa Logic zrobi:

doLogic() 
    { 
     if (n > 5) 
     { 
     throw "n is greater than 5"; 
     } 
     ///Something more 
    } 

a warstwa widok mógłby zrobić:

try 
{ 
    doLogic() 
} 
catch (const char *e) 
{ 
    MessageBox(0, e, 0, 0); 
    return; 
} 

ale znowu, jak inny powiedział: Najważniejszą rzeczą jest skąd pochodzą z n. Jeśli spodziewasz się, że będzie to więcej niż 5, po prostu użyj if() else, not exceptions. Ale jeśli n to zawsze mniej niż 5, a jeśli jest więcej niż 5 oznacza, że ​​coś jest nie tak z twoim systemem, użyj wyjątków.