Obsługa sytuacji
wyjątkowych
Wykrywanie sytuacji wyjątkowych
Reakcja na wystąpienie wyjątku
Programowe wywołanie wyjątku
Sytuacje wyjątkowe a obiektowość
Słowa kluczowe dotyczące
obsługi wyjątków
wyjątek (ang. exception) wystąpienie w
programie sytuacji nadzwyczajnej, nie
przewidzianej w podstawowym algorytmie
programu
try { ...}; - (ang. próbować) blok
instrukcji w których podejrzewamy że może
wystąpić sytuacja wyjątkowa
throw obiekt; - (ang. rzucać) powoduje
programowe wywołanie sytuacji wyjątkowej
catch (typ_argumentu){...}; -
(ang. łapać) powoduje programowe
przechwycenie obsługi wyjątku
Wykrycie wystąpienia sytuacji
wyjątkowej
Instrukcje programu, które mogą
wywołać wystąpienie sytuacji
wyjątkowej (wyjątku) należy
zamknąć w bloku o nazwie try
try {
A = StrToFloat(Edit1->Text);
};
Przechwycenie obsługi sytuacji
wyjątkowej
Po wystąpieniu wyjątku wewnątrz bloku try
następuje wyskok z miejsca wystąpienia do
najbliższego bloku obsługi sytuacji
wyjątkowych catch o pasującym argumencie
Istnieje wersja uniwersalna, przechwytująca
wszystkie typy wyjątków
catch(...){
MessageDlg(”Błąd”,mtError,
(TMsgDlgButton)4,0);
};
Programowe wywołanie wyjątku
Aby wywołać wyjątek należy użyć słowa
kluczowego throw:
throw Obiekt;
Element „rzucany” jest nazywany obiektem
wyjątku (exception object) lub argumentem
wyjątku (exception parameter)
Typ „rzucanego” argumentu może być
przechwytywany w blokach catch umożliwiając
różne reakcje na różne sytuacje wyjątkowe
Przesyłanie informacji o wyjątku
Wyłącznie przez typ argumentu – nie interesuje nas
konkretna wartość:
try{ throw (double)A; };
catch (double) {
//rzucono typ double }
Poza typem wykorzystujemy wartość argumentu:
catch (double Arg) {
Label1->Caption = FloatToStr(Arg);
}
Dotyczy to typów wbudowanych i zdefiniowanych
Zastosowanie mechanizmu obsługi
wyjątków
Najczęściej: współpraca odmiennych
fragmentów kodu (np. wywoływanie funkcji
bibliotecznych)
Funkcja biblioteczna potrafi wykryć błąd (np.
niepoprawny argument) ale nie potrafi
zareagować (np. wyświetlić komunikatu
użytkownikowi)
W drugim fragmencie kodu (np. pisanym
programie) można odpowiednio zareagować ale
jest trudność z wykryciem zaistnienia błędu
Przykład użycia wielu bloków catch
try{...
throw (int)A; // argument typu int
...
throw (char)B; // argument typu char
}
catch (int){ //obsługa wyjątku jeżeli argument
}
// był typu int
catch (char){ // obsługa wyjątku jeżeli argument
}
// był typu char
Działanie wielu bloków catch
W praktyce często umieszcza się kolejno po
sobie wiele bloków catch
Każdy blok jest wykonywany w odpowiedzi
na zaistnienie jednego typu sytuacji
wyjątkowych („złapanie” obiektu jednego
typu)
Blok catch nie zawiera instrukcji break, po
zakończeniu wykonywania instrukcji w
danym bloku wszystkie pozostałe zostaną
pominięte
Działanie wielu bloków catch c.d.
Dopasowanie typów
W ciągu bloków catch zostaną wykonane
instrukcje pierwszego bloku, którego typ
zostanie dopasowany do typu argumentu
Pozostałe bloki zostaną zignorowane, nawet jeżeli
typ argumentu był lepiej dopasowany (w C++
Builder - Warning)
Wniosek: ma znaczenie kolejność bloków
catch
w szczególności bloki przechwytujące obiekty klas
pochodnych powinny być umieszczane najpierw
Zagnieżdżenie bloków try - catch
Bloki try – catch można zagnieżdżać na dowolnym
poziomie
W szczególności – w bloku try – catch można np.
wywołać funkcję mającą własny blok obsługi wyjątków
try{
// -> blok zewnętrzny
try{ /* blok wewnętrzny */}
catch(int){ };
// obsługa wyjątku wewn.
catch(float){ }; // obsługa wyjątku wewn.
// instrukcje;
}
catch(char){ ... }
// obsługa wyjątku zewn.
Mechanizm obsługi zagnieżdżonych
wyjątków
Wyjątek rzucony w najbardziej zagnieżdżonym bloku
try jest obsługiwany w pierwszej kolejności przez
odpowiadający mu blok catch
Jeżeli nie zostanie znaleziony pasujący blok,
sprawdzany jest zewnętrzny blok catch
Po wykonaniu bloku catch jest kontynuowane
wykonywanie programu na poziomie, na którym był
wykonany catch
Jeżeli nie zostanie wykonany żaden blok obsługi
wyjątku, zostanie wywołana specjalna funkcja
terminate kończąca program (lub standardowa
procedura obsługi wyjątku np. dla wyjątków VCL)
Powtórne rzucenie wyjątku
Stosowane przy zagnieżdżeniu bloków
try - catch
Wyjątek „przechwycony” w bloku
wewnętrznym można ponownie rzucić aby
został „złapany” przez blok zewnętrzny:
throw; // bez parametrów
Instrukcja używana jest w wewnętrznym bloku
catch
zostanie rzucony ten sam obiekt
Blok catch przechwytujący
wszystkie wyjątki
Blok taki jest definiowany następująco
catch(...){ // instrukcje
}
Blok ten powinien być umieszczany na
końcu listy bloków
Nie potrafi odczytać typu obiektu, który
został przysłany jako argument
W praktyce może zostać wykorzystany np.
w wewnętrznym bloku try – catch wraz
z instrukcją powtórnego rzucenia throw;
Rzucenie wyjątku w bloku catch
Instrukcje w bloku catch można
potraktować jako zwykły kod
programu
Jeżeli zaistnieje taka potrzeba –
w bloku catch można zagnieździć
kolejny blok try – catch
Działa tutaj znany już mechanizm
obsługi wyjątków zagnieżdżonych
Uruchomienie procedury obsługi
wyjątku
W przypadku rzucenia wyjątku:
int A = 5;
throw A;
Procedura obsługi wyjątku (blok catch) zostaje
uruchomiona, jeżeli:
Typ argumentu rzucanego jest identyczny z typem
oczekiwanym:
catch (int Arg) {...}
Przy typie oczekiwanym jest umieszczony przydomek
const:
catch (const int Arg){...}
Występuje referencja do obiektu typu oczekiwanego:
catch (int & Arg){...}
Uruchomienie procedury obsługi
wyjątku przy niezgodności typów
Procedura obsługi wyjątku zostanie uruchomiona,
jeżeli argumentem w catch jest obiekt klasy
podstawowej względem argumentu throw:
class TPunkt {...};
class TWektor: public TPunkt {};
TWektor W1;
throw W1;
catch(TPunkt P){...}
Uruchomienie procedury obsługi
wyjątku przy niezgodności typów c.d.
Procedura obsługi wyjątku zostanie
uruchomiona, jeżeli:
Argumentem throw jest wskaźnik do
obiektu klasy A,
Argumentem w catch jest wskaźnik do
obiektu klasy B,
Jest zdefiniowana standardowa konwersja
B → A
int *A;
throw A;
catch(void *X){...}
Wyjątki w bibliotece VCL
Podstawową klasą wyjątku w bibliotece VCL
jest
Exception
Z tej klasy wywodzą się m.in. klasy
pokazane na kolejnych slajdach
Exception nie jest klasą abstrakcyjną –
można używać jej w bloku catch – zostaną
wtedy przechwycone wszystkie wyjątki klas
potomnych
Obiekty wyjątków zdefiniowanych w VCL
należy przesyłać do bloku catch przez
referencję:
catch (Exception & E){. . .}
Zdefiniowane klasy wyjątków
Represents a file I/O error.
EInOutError
Signifies an unrecognized exception code.
EExternalException
Catches integer divide-by-zero errors.
EDivByZero
Catches data incompatible with a specified mask.
EDBEditError
Specifies a database access error.
EDatabaseError
Indicates string or object conversion errors.
EConvertError
Signals an invalid attempt to register or rename a component.
EComponentError
Prevents invalid attempts to access a Boolean array.
EBitsError
Checks for invalid memory access errors.
EAccessViolation
Stops a sequence of events without displaying an error
message dialog box.
EAbort
Description
Exception class
Catches floating-point divide-by-zero errors.
EZeroDivide
Specifies registry errors.
ERegistryException
Indicates an integer value that is too large for the declared
type to which it is assigned.
ERangeError
Occurs on unsuccessful attempts to set the value of a
property.
EPropertyError
Signals a printing error.
EPrinterError
Specifies OLE automation errors.
EOleError
Detects problems with linking to ActiveX controls.
EOleCtrlError
Involves a problem with menu item.
EMenuError
Results from invalid pointer operations.
EInvalidPointer
Occurs when invalid operations are attempted on a
component.
EInvalidOperation
Indicates an attempt to work with an unrecognized graphic
file format.
EInvalidGraphic
Checks for illegal typecasting.
EInvalidCast
Specifies integer calculations whose results are too large for
the allocated register.
EIntOverflow
Właściwości obiektu klasy
Exception
HelpContext – identyfikator
kontekstu tematu pomocy
związanego z wywołanym wyjątkiem
Message – tekst komunikatu
opisującego rodzaj wyjątku, który
wystąpił
Metody obiektu klasy Exception
Creates an instance of an exception with a help-context ID and
a simple message string that is loaded from the application's
resources.
CreateResHelp
(public)
Creates an instance of an exception with a help-context ID and
a formatted message string loaded from the application
resources
CreateResFmtHelp
(public)
Creates an instance of an exception with a message string that
is loaded from the application's resources and then formatted.
CreateResFmt
(public)
Creates an instance of an exception with a simple message
string that is loaded from the application's resources.
CreateRes (public)
Creates an instance of an exception with a simple message
string and a help- context ID.
CreateHelp (public)
Instantiates an instance of an exception with a formatted
message string and a help-context ID.
CreateFmtHelp
(public)
Instantiates an instance of an exception with a formatted
message string.
CreateFmt (public)
Instantiates an instance of an exception with a simple message
string.
Create (public)
Description
Method
Obsługa wyjątków w innych
językach obiektowych
Java – podobnie jak w C++
try{
UIManager.setLookAndFeel(
UIManager.getCrossPlatformLookAndFeelClassname());
}catch(Exception e){
System.out.println("Nie mogę zastosować techniki"+
"Look&Feel");
}
Obsługa wyjątków w innych
językach obiektowych
Object Pascal – dwa typy bloków chronionych
try
Ini := TIniFile.Create;
W := Ini.ReadInteger('Opcje',‘Dlugosc',100);
finally
Ini.Free;
end;
try
W := StrToInt(Edit1.Text);
except
W := 0;
end;