Wyjątki. Po co nam wyjątki? Często pisząc jakiś kod staramy się go uczynić uniwersalnym, jesteśmy w stanie wykryć sytuacje niepoprawne, ale nasz kod może.

Slides:



Advertisements
Podobne prezentacje
Tablice 1. Deklaracja tablicy
Advertisements

C++ wykład 9 ( ) Szablony.
C++ wykład 2 ( ) Klasy i obiekty.
C++ wykład 4 ( ) Przeciążanie operatorów.
Język C/C++ Funkcje.
C++ wykład 7 ( ) Wyjątki.
Programowanie obiektowe
Związki w UML.
Klasy abstrakcyjne i interfejsy
Deklaracje i definicje klas w C++ Składowe, pola, metody Konstruktory
Dzisiejszy wykład Wyjątki.
Programowanie obiektowe
Wzorce.
Język ANSI C Funkcje Wykład: Programowanie komputerów
Prowadzący: mgr inż. Elżbieta Majka
Programowanie I Rekurencja.
Static, const, volatile.
Bezpieczeństwo wyjątków w C++: OpenGL
PROGRAMOWANIE STRUKTURALNE
Szablony (wzorce) Przykład 1: Szablon klasy -
Licznik template<class Count_Type> class Count { public:
Bartosz Walter Inżynieria oprogramowania Lecture XXX JavaTM – część II Bartosz Walter
Tablice.
Dziedziczenie i jego rodzaje
C++ wykład 2 ( ) Klasy i obiekty.
C++ wykład 7 ( ) Wyjątki. Ogólne spojrzenie na wyjątki Wyjątki zaprojektowano do wspierania obsługi błędów. System wyjątków dotyczy zdarzeń synchronicznych.
Zasady zaliczenia Warunki uzyskania zaliczenia:
Temat nr 10: System przerwań
Podstawy programowania II
Podstawy programowania
Programowanie urządzeń mobilnych – wykład IV
Java 3 MPDI Programowanie obiektowe W7. import java.io.*; public class X { // kontrukcja throws – określenie jakie wyjątki może dana metoda // sygnalizować
Podstawy programowania II
Programowanie obiektowe III rok EiT
Programowanie obiektowe III rok EiT
Andrzej Repak Nr albumu
Java – coś na temat Klas Piotr Rosik
Inicjalizacja i sprzątanie
Seminarium problemowe
Programowanie obiektowe Wykład 3 dr Dariusz Wardowski, Katedra Analizy Nieliniowej, WMiI UŁ 1/21 Dariusz Wardowski.
Programowanie obiektowe Wykład 7 dr Dariusz Wardowski, Katedra Analizy Nieliniowej, WMiI UŁ 1/20 Dariusz Wardowski.
Programowanie obiektowe Wykład 6 dr Dariusz Wardowski, Katedra Analizy Nieliniowej, WMiI UŁ 1/14 Dariusz Wardowski.
Przerwanie ang. interrupt.
Warsztaty C# Część 6 Grzegorz Piotrowski Grupa .NET PO
Podstawy informatyki 2013/2014 Łukasz Sztangret Katedra Informatyki Stosowanej i Modelowania Prezentacja przygotowana w oparciu o materiały Danuty Szeligi.
Przekazywanie parametrów do funkcji oraz zmienne globalne i lokalne
Programowanie obiektowe 2013/2014
Kurs języka C++ – wykład 9 ( )
Kurs języka C++ – wykład 5 ( )
K URS JĘZYKA C++ – WYKŁAD 7 ( ) Wyjątki.
K URS JĘZYKA C++ – WYKŁAD 10 ( ) Szablony.
Programowanie strukturalne i obiektowe C++
Kurs języka C++ – wykład 4 ( )
Programowanie obiektowe Wykład 9 dr Dariusz Wardowski, Katedra Analizy Nieliniowej, WMiI UŁ 1/15 Dariusz Wardowski.
Dziedziczenie wielobazowe. dana klasa może mieć kilka bezpośrednich klas bazowych: dana klasa może mieć kilka bezpośrednich klas bazowych: kolorpołożenie.
Zestaw pytań nr. 3 Typy generyczne Wyjątki OPRACOWALI: JAKUB GRYCZEWSKIKINGA ROSA DANIEL KAPTEJNYWOJCIECH ŁĘCZYCKI
Dziedziczenie Wykład 7 Dziedziczenie sekwencyjne
PO13-1 / 19 Wykład 13 Wyjątki i ich zgłaszanie Wyłapywanie wyjątków Obsługa wyjątków Wykorzystanie polimorfizmu Filtrowanie wyjątków Błędy w konstruktorach.
Podstawy informatyki Tablice Łukasz Sztangret Katedra Informatyki Stosowanej i Modelowania Prezentacja przygotowana w oparciu o materiały Danuty Szeligi.
Podstawy informatyki Funkcje Łukasz Sztangret Katedra Informatyki Stosowanej i Modelowania Prezentacja przygotowana w oparciu o materiały Danuty Szeligi.
Łukasz Sztangret Katedra Informatyki Stosowanej i Modelowania Prezentacja przygotowana w oparciu o materiały Danuty Szeligi i Pawła Jerzego Matuszyka Podstawy.
Podstawy informatyki Operatory rzutowania Łukasz Sztangret Katedra Informatyki Stosowanej i Modelowania Prezentacja przygotowana w oparciu o materiały.
Podstawy informatyki Mechanizm obsługi sytuacji wyjątkowych Łukasz Sztangret Katedra Informatyki Stosowanej i Modelowania Prezentacja przygotowana w oparciu.
Programowanie Obiektowe – Wykład 6
Dzisiejsze zajęcia będą wyjątkowe…
Kurs języka C++ – wykład 3 ( )
Programowanie Obiektowe – Wykład 2
Język C++ Typy Łukasz Sztangret Katedra Informatyki Stosowanej i Modelowania Prezentacja przygotowana w oparciu o materiały Danuty Szeligi i Pawła Jerzego.
Zapis prezentacji:

Wyjątki

Po co nam wyjątki? Często pisząc jakiś kod staramy się go uczynić uniwersalnym, jesteśmy w stanie wykryć sytuacje niepoprawne, ale nasz kod może być używany na różny sposób, nie jesteśmy w stanie przewidzieć jak zareagować na błąd. Często pisząc jakiś kod staramy się go uczynić uniwersalnym, jesteśmy w stanie wykryć sytuacje niepoprawne, ale nasz kod może być używany na różny sposób, nie jesteśmy w stanie przewidzieć jak zareagować na błąd. Ze strony kogoś korzystającego z danej biblioteki sytuacja odwrotna – wiadomo jak obsłużyć, ale nie wiadomo jak wykryć. Ze strony kogoś korzystającego z danej biblioteki sytuacja odwrotna – wiadomo jak obsłużyć, ale nie wiadomo jak wykryć.

Wyjątki w C++ W C++ wprowadzono mechanizm wyjątków, jako sposób na zgłaszanie błędów w momencie ich wykrycia i na definiowanie zachowania programu w przypadku pojawienia się błędów. Obsługa wyjątków realizowana jest w C++ z użyciem słów kluczowych catch throw i try. W C++ wprowadzono mechanizm wyjątków, jako sposób na zgłaszanie błędów w momencie ich wykrycia i na definiowanie zachowania programu w przypadku pojawienia się błędów. Obsługa wyjątków realizowana jest w C++ z użyciem słów kluczowych catch throw i try. throw — zgłoszenie wyjątku throw — zgłoszenie wyjątku try — poprzedza blok instrukcji (obowiązkowo w nawiasach klamrowych) w którym można spodziewać się wystąpienia wyjątków try — poprzedza blok instrukcji (obowiązkowo w nawiasach klamrowych) w którym można spodziewać się wystąpienia wyjątków catch — definiuje reakcję na wystąpienie wyjątku (też obowiązują nawiasy). catch — definiuje reakcję na wystąpienie wyjątku (też obowiązują nawiasy).

throw, try i catch double funkcja()// funkcja która o niepowodzeniu // swoich obliczeń informuje // swoich obliczeń informuje // zgłaszając wyjątek // zgłaszając wyjątek{ // pewne obliczenia // pewne obliczenia // w razie wykrycia błędu // w razie wykrycia błędu throw 1; // zgłoszenie wyjątku throw 1; // zgłoszenie wyjątku // w przeciwnym przypadku dalsze obliczenia // w przeciwnym przypadku dalsze obliczenia // wykryto inny błąd // wykryto inny błąd throw 2; // zgłoszenie innego wyjątku throw 2; // zgłoszenie innego wyjątku //... //...}

void przykl0() { try// wykonujemy operacje, przewidujemy try// wykonujemy operacje, przewidujemy // możliwość zgłoszenia przez nie wyjątku // możliwość zgłoszenia przez nie wyjątku { // klamra obowiązkowa ! { // klamra obowiązkowa ! funkcja(); funkcja(); cout << „bez błędów :-) "; cout << „bez błędów :-) "; } catch (int i) // w przypadku zgłoszenia wyjątku catch (int i) // w przypadku zgłoszenia wyjątku // w bloku po try sterowanie zostanie // w bloku po try sterowanie zostanie // przekazane do bloku instrukcji po catch // przekazane do bloku instrukcji po catch // (do tzw.: procedury obsługi wyjątku) // (do tzw.: procedury obsługi wyjątku) { // klamra obowiązkowa ! { // klamra obowiązkowa ! cout << "wykryto błąd " << i; cout << "wykryto błąd " << i; } // jeżeli funkcja funkcja() zakończy się poprawnie // jeżeli funkcja funkcja() zakończy się poprawnie // (bez zgłaszania wyjątku), to procedura obsługi wyjątku zostanie // (bez zgłaszania wyjątku), to procedura obsługi wyjątku zostanie // pominięta i rozpocznie się wykonywanie dalszych instrukcji // pominięta i rozpocznie się wykonywanie dalszych instrukcji // dalsze instrukcje // dalsze instrukcje cout << „koniec przykladu 0 "; cout << „koniec przykladu 0 ";}

throw, try i catch throw – jest operatorem, po nim następuje wyrażenie które określi rodzaj wyjątku, mogą być różne typy/klasy wyjątków; throw – jest operatorem, po nim następuje wyrażenie które określi rodzaj wyjątku, mogą być różne typy/klasy wyjątków; catch – może pojawić się tylko po try lub po innym catch, w nawiasie określamy typ wyjątku i zmienną/obiekt która przekazuje informacje o wyjątku. catch – może pojawić się tylko po try lub po innym catch, w nawiasie określamy typ wyjątku i zmienną/obiekt która przekazuje informacje o wyjątku. Jeżeli do obsługo błędu wystarczy sam fakt jego wykrycia to podajemy typ nie podając zmiennej/obiektu. Jeżeli do obsługo błędu wystarczy sam fakt jego wykrycia to podajemy typ nie podając zmiennej/obiektu. Blok po catch nazywamy procedurą obsługi wyjątku. Blok po catch nazywamy procedurą obsługi wyjątku. Procedura obsługi wyjątku może znajdować się w tej samej funkcji w której następuje zgłoszenie wyjątku. Procedura obsługi wyjątku może znajdować się w tej samej funkcji w której następuje zgłoszenie wyjątku.

void przykl1() { try try { // obliczenia i niepowodzenie // obliczenia i niepowodzenie throw ‘a’; throw ‘a’; // dalsze obliczenia i dalsze niepowodzenia // dalsze obliczenia i dalsze niepowodzenia throw 1; throw 1; //... //... } catch (int i) catch (int i) { cout << "wykryto błąd numer " << i; cout << "wykryto błąd numer " << i; } catch (char) catch (char) { cout << "wykryto błąd bez numeru"; cout << "wykryto błąd bez numeru"; }}

Obsługa zgłoszenia wyjątku W momencie wykrycia wyjątku przeglądany jest stos od funkcji w której zgłoszono wyjątek przez łańcuch wywołań funkcji aż do main(). W momencie wykrycia wyjątku przeglądany jest stos od funkcji w której zgłoszono wyjątek przez łańcuch wywołań funkcji aż do main(). Przy wychodzeniu „w górę” wykonywane są destrukcje obiektów lokalnych (tak jak przy normalnym opuszczeniu funkcji). Przy wychodzeniu „w górę” wykonywane są destrukcje obiektów lokalnych (tak jak przy normalnym opuszczeniu funkcji). Jeżeli nie napotka się nigdzie procedury obsługi zgłoszonego wyjątku (może być ich więcej niż jedna) to nastąpi przerwanie programu. Jeżeli nie napotka się nigdzie procedury obsługi zgłoszonego wyjątku (może być ich więcej niż jedna) to nastąpi przerwanie programu. Jeżeli jest kilka na różnych poziomach zagnieżdzenia (wywołań funkcji) to wykonana zostanie najwcześniej znaleziona, czyli ta którą sterowanie minęło jako ostatnią. Jeżeli jest kilka na różnych poziomach zagnieżdzenia (wywołań funkcji) to wykonana zostanie najwcześniej znaleziona, czyli ta którą sterowanie minęło jako ostatnią.

Obsługa zgłoszenia wyjątku void przykl2() { try try { przykl0(); przykl0(); } catch (int i) catch (int i) { cout << "wykryto błąd numer " << i; cout << "wykryto błąd numer " << i; // ten wyjątek zgłaszany przez funkcja() // ten wyjątek zgłaszany przez funkcja() // jest obsługiwany już w przykl0(), // jest obsługiwany już w przykl0(), // więc ta procedura obsługi wyjątku nie zostanie wykonana // więc ta procedura obsługi wyjątku nie zostanie wykonana }}

Ponowne zgłoszenie wyjątku Wyjątek jest uznawany obsłużony w momencie rozpoczęcia wykonywania procedury obsługi wyjątku — następujący kod nie powoduje zapętlenia: Wyjątek jest uznawany obsłużony w momencie rozpoczęcia wykonywania procedury obsługi wyjątku — następujący kod nie powoduje zapętlenia: try try { // pwoduje wystąpienie wyjątku klasy xxx { // pwoduje wystąpienie wyjątku klasy xxx } catch (xxx) catch (xxx) { // nieudana próba naprawy { // nieudana próba naprawy throw xxx; // pójdzie „w górę” do kodu który wywołał ten throw xxx; // pójdzie „w górę” do kodu który wywołał ten } Operator throw bez argumentu w procedurze obsługi wyjątku powoduje ponowne jego zgłoszenie. Operator throw bez argumentu w procedurze obsługi wyjątku powoduje ponowne jego zgłoszenie. Tutaj zamiast „throw xxx;” wystarczyłoby napisać „throw;”. Tutaj zamiast „throw xxx;” wystarczyłoby napisać „throw;”.

Zagnieżdzanie procedur obsługi try { // kod, który może zgłosić wyjątek klasy zzz } catch (zzz) { try // próbujemy coś zrobić z wyjątkiem try // próbujemy coś zrobić z wyjątkiem { // próba może się nie powieść, kod naprawy // próba może się nie powieść, kod naprawy // też może zgłosić wyjątek klasy zzz // też może zgłosić wyjątek klasy zzz throw; // znaczy to samo co „throw zzz;”, throw; // znaczy to samo co „throw zzz;”, } catch (zzz) catch (zzz) { // obsługa wyjątku zgłoszonego podczas obsługi wyjątku { // obsługa wyjątku zgłoszonego podczas obsługi wyjątku }}

Klasy wyjątków Można zdefiniować wiele klas wyjątków, albo do opisu wyjątku wykorzystać istniejące już typy/klasy. Można zdefiniować wiele klas wyjątków, albo do opisu wyjątku wykorzystać istniejące już typy/klasy. W bibliotekach klas korzystających z wyjątków zazwyczaj korzysta się ze specjalnych klas do określania rodzaju wyjątków. W bibliotekach klas korzystających z wyjątków zazwyczaj korzysta się ze specjalnych klas do określania rodzaju wyjątków. Stosowanie klas jako typów wyjątków jest wygodne, możemy tworzyć klasy o nazwach opisujących typy wyjątków, Stosowanie klas jako typów wyjątków jest wygodne, możemy tworzyć klasy o nazwach opisujących typy wyjątków,

Klasy wyjątków Przykład: klasa błędu: dielenie przez zero Przykład: klasa błędu: dielenie przez zero class błąd_dzielenia_przez_0 {}; w razie potrzeby zgłoszenia wyjątku korzystamy z konstruktora w razie potrzeby zgłoszenia wyjątku korzystamy z konstruktora throw błąd_dzielenia_przez_0(); i wyłapujemy wyjątek: i wyłapujemy wyjątek: catch (błąd_dzielenia_przez_0) { /*... */ } W powyższym przykładzie skorzystaliśmy z klasy (a nie z obiektu, przez konstruktory parametrowe możemy również przekazywać obiekty o istotnej wartości) W powyższym przykładzie skorzystaliśmy z klasy (a nie z obiektu, przez konstruktory parametrowe możemy również przekazywać obiekty o istotnej wartości)

Dziedziczenie klas wyjątków Przy obsłudze klas wyjątków możemy również skorzystać z dziedziczenia – procedura obsługi wyjątku klasy bazowej obsłuży wyjątek klasy pochodnej (niejawna konwersja automatyczna – ale uwaga: tylko dziedziczącej klasę bazową publicznie). Przy obsłudze klas wyjątków możemy również skorzystać z dziedziczenia – procedura obsługi wyjątku klasy bazowej obsłuży wyjątek klasy pochodnej (niejawna konwersja automatyczna – ale uwaga: tylko dziedziczącej klasę bazową publicznie). class blad_matematyczny {}; class nadmiar:public blad_matematyczny {}; class niedomiar:public blad_matematyczny {}; class dzielenie_przez_0:public blad_matematyczny {};

Jeżeli jest kilka procedur obsługi wyjątku mogących obsłużyć dany wyjątek, to zostanie wykonana pierwsza (najbliższa bloku try) z nich. Jeżeli jest kilka procedur obsługi wyjątku mogących obsłużyć dany wyjątek, to zostanie wykonana pierwsza (najbliższa bloku try) z nich.try{ throw nadmiar(); throw nadmiar();} catch(nadmiar) // obsługa nadmiaru i wyjątków klas {// pochodnych od nadmiar cout << "\nnadmiar"; cout << "\nnadmiar";} catch(blad_matematyczny) // obsługa błędów matematycznych i jego { // pochodnych, za wyjątkiem już obsłużonego cout << "\nbm"; // nadmiaru i wyjątków cout << "\nbm"; // nadmiaru i wyjątków } // klas pochodnych od nadmiar Dziedziczenie klas wyjątków

Gdyby obsługa błędu_matematycznego poprzedzała obsługę nadmiaru to obsługiwała by zawsze również nadmiar: Gdyby obsługa błędu_matematycznego poprzedzała obsługę nadmiaru to obsługiwała by zawsze również nadmiar:try{ throw nadmiar(); throw nadmiar();} catch(blad_matematyczny) // obsługa błędów matematycznych {// i pochodnych klasy blad_matematyczny cout << "\nbm"; cout << "\nbm";} catch(nadmiar) // obsługa nadmiaru i wyjątków klas pochodnych od nadmiar // nie zostanie nigdy wykorzystana bo te wyjątki obsługuje // nie zostanie nigdy wykorzystana bo te wyjątki obsługuje { // procedura obsługi wyjątku blad_matematyczny cout << "\nnadmiar"; cout << "\nnadmiar";} Dziedziczenie klas wyjątków

Obsługa nieobsłużonych wyjątków Za pomocą instrukcji catch(...) tworzymy procedurę obsługi wszystkich klas wyjątków Za pomocą instrukcji catch(...) tworzymy procedurę obsługi wszystkich klas wyjątków void m() { try try { // coś // coś } catch(...) catch(...) { // zrób porządki po niedokończonej funkcji // zrób porządki po niedokończonej funkcji throw; // powtórnie zgłoś wyjątek jako sygnał niepowodzenia throw; // powtórnie zgłoś wyjątek jako sygnał niepowodzenia }}

Specyfikowanie jawne wyjątków zgłaszanych przez metody void C::met() throw(int) { // coś throw(12); throw(12); // coś } To nie jest obowiązkowe To nie jest obowiązkowe Ale przyda się programiscie używającemu met() Ale przyda się programiscie używającemu met()

Specyfikowanie jawne wyjątków zgłaszanych przez metody void C::met() throw() { // coś // throw zabronione tutaj! // throw zabronione tutaj! // coś }

Obsługa niewyspecyfikowanych wyjątków set_unexpected (my_unexpected) set_unexpected (my_unexpected) ustawia handler niewyspecyfikowanych wyjątków ustawia handler niewyspecyfikowanych wyjątków domyślny handler (void unexpected()) wywołuje terminate() domyślny handler (void unexpected()) wywołuje terminate() handler będzie użyty jeżeli wyrzucony wyjątek nie zgadza się ze specyfikacją wyjątków rzucającej funkcji handler będzie użyty jeżeli wyrzucony wyjątek nie zgadza się ze specyfikacją wyjątków rzucającej funkcji jeżeli rzucająca funkcja specyfikuje, że może wyrzucić bad_exception, to powtórne wyrzucenie wyjątku przez handler, albo wyrzucenie innego niewyspecyfikowanego wyjątku, spowoduje automatyczne wyrzucenie wyjątku bad_exception jeżeli rzucająca funkcja specyfikuje, że może wyrzucić bad_exception, to powtórne wyrzucenie wyjątku przez handler, albo wyrzucenie innego niewyspecyfikowanego wyjątku, spowoduje automatyczne wyrzucenie wyjątku bad_exception

Wyjątki w bibliotece standardowej Składniki biblioteki standardowej wyrzucają wyjątki klas dziedziczących po: class exception // std::exception { public: exception () throw(); exception (const exception&) throw(); exception& operator= (const exception&) throw(); virtual ~exception() throw(); virtual const char* what() const throw(); // zwróć opis // null-terminated, treść zależna od implementacji biblioteki // null-terminated, treść zależna od implementacji biblioteki}

Wyjątki w bibliotece standardowej Składniki biblioteki standardowej wyrzucają wyjątki (std::) : bad_alloc bad_alloc wyrzuca new w przypadku niepowodzenia alokacji bad_cast bad_cast rzuca dynamic_cast gdy nie powiedzie się konwersja referencji bad_exception bad_exception gdy typ wyjątku nie pasuje do żadnego catch, lub do typów wyspecyfikowanych w nagłówku funkcji rzucającej (po wywołaniu unexpected()) bad_typeid bad_typeid rzuca typeid np. gdy otrzyma jako argument NULL rzuca typeid np. gdy otrzyma jako argument NULL

Wyjątki w bibliotece standardowej Składniki biblioteki standardowej wyrzucają wyjątki (std::) : runtime_error runtime_error klasa bazowa dla klas definiujących wyjątki czasu wykonania programu (range_error, overflow_error, underflow_error) logic_error logic_error dla błędów wewnętrznej logiki programu; klasa bazowa dla innych (domain_error, invalid_argument, length_error, out_of_range) ios_base::failure ios_base::failure błędy zgłaszane przez bibliotekę iostream …