Ponad 10 lat temu w szkole uczyli cię używania specyfikatorów wyjątków. Ponieważ moje doświadczenie jest jednym z nich, programiści Torvaldish C, którzy uparcie unikają C ++, chyba że są do tego zmuszeni, trafiam tylko do C ++ sporadycznie, a kiedy to robię, nadal używam specyfikatorów wyjątków, ponieważ tego się nauczono.
Jednak większość programistów C ++ marszczy brwi w stosunku do specyfikatorów wyjątków. Przeczytałem debatę i argumenty różnych guru C ++, takich jak te . O ile rozumiem, sprowadza się do trzech rzeczy:
- Specyfikatory wyjątków używają systemu typów, który jest niezgodny z resztą języka („system typów cieni”).
- Jeśli twoja funkcja ze specyfikatorem wyjątku wyrzuci cokolwiek innego niż to, co określiłeś, program zostanie zakończony w zły, nieoczekiwany sposób.
- Specyfikatory wyjątków zostaną usunięte w nadchodzącym standardzie C ++.
Czy coś tu brakuje, czy to z tych wszystkich powodów?
Moje własne opinie:
Odnośnie 1): Więc co. C ++ jest prawdopodobnie najbardziej niespójnym językiem programowania, jaki kiedykolwiek stworzono, pod względem składniowym. Mamy makra, goto / etykiety, hordę (skarb?) O zachowaniu niezdefiniowanym / nieokreślonym / implementacji, źle zdefiniowane typy liczb całkowitych, wszystkie reguły promocji typu domyślnego, słowa kluczowe ze specjalnymi przypadkami, takie jak przyjaciel, auto , zarejestruj się, wyraźne ... I tak dalej. Ktoś prawdopodobnie mógłby napisać kilka grubych książek o całej dziwności w C / C ++. Dlaczego więc ludzie reagują na tę szczególną niekonsekwencję, która jest drobną wadą w porównaniu z wieloma innymi znacznie bardziej niebezpiecznymi cechami języka?
Odnośnie 2): Czy to nie moja własna odpowiedzialność? Jest tak wiele innych sposobów, aby napisać fatalny błąd w C ++, dlaczego ten konkretny przypadek jest jeszcze gorszy? Zamiast pisać, throw(int)
a następnie rzucać Crash_t, mogę równie dobrze twierdzić, że moja funkcja zwraca wskaźnik do int, a następnie utworzyć dziki, wyraźny typecast i zwrócić wskaźnik do Crash_t. Duchem C / C ++ zawsze było pozostawienie większości odpowiedzialności programistom.
A co z zaletami? Najbardziej oczywiste jest to, że jeśli twoja funkcja próbuje jawnie wyrzucić dowolny typ inny niż określony, kompilator wyświetli błąd. Uważam, że standard jest jasny w tym zakresie (?). Błędy będą występować tylko wtedy, gdy funkcja wywołuje inne funkcje, które z kolei generują niewłaściwy typ.
Pochodząc ze świata deterministycznych, osadzonych programów C, z pewnością wolałbym wiedzieć dokładnie, co rzuci na mnie funkcja. Jeśli jest coś w tym języku, dlaczego tego nie użyć? Alternatywami wydają się być:
void func() throw(Egg_t);
i
void func(); // This function throws an Egg_t
Myślę, że istnieje duża szansa, że osoba dzwoniąca zignoruje / zapomni wdrożyć try-catch w drugim przypadku, a mniej w pierwszym przypadku.
Jak rozumiem, jeśli jedna z tych dwóch form zdecyduje się nagle rzucić inny rodzaj wyjątku, program się zawiesi. W pierwszym przypadku, ponieważ nie wolno rzucać innego wyjątku, w drugim przypadku, ponieważ nikt nie spodziewał się, że wyrzuci SpanishInquisition_t, a zatem to wyrażenie nie jest rejestrowane tam, gdzie powinno być.
W przypadku tego ostatniego, złapanie w ostateczności (...) na najwyższym poziomie programu nie wydaje się wcale lepsze niż awaria programu: „Hej, gdzieś w twoim programie coś rzuciło dziwny, nieobsługiwany wyjątek . ” Nie możesz odzyskać programu, gdy jesteś tak daleko od miejsca zgłoszenia wyjątku, jedyne, co możesz zrobić, to wyjść z programu.
A z punktu widzenia użytkownika nie obchodzi ich to, że otrzymają z systemu operacyjnego złą wiadomość z komunikatem „Program zakończony. Blablabla pod adresem 0x12345” lub złą wiadomość z twojego programu z informacją „Nieobsługiwany wyjątek: mojaklasa. func.something ”. Błąd jest nadal obecny.
W nadchodzącym standardzie C ++ nie będę miał innej opcji, jak zrezygnować ze specyfikatorów wyjątków. Ale wolałbym raczej wysłuchać solidnego argumentu, dlaczego są źli, niż „Jego Świątobliwość to stwierdził i tak jest”. Być może jest więcej argumentów przeciwko nim niż te, które wymieniłem, a może jest ich więcej, niż zdaję sobie sprawę?