Na błędy najlepsze są wyjątki
Bez wyjątków
n-
;le-
ie-
a-
ze-
Ły-
io
^g-
ba-
nał
;ó-
ia
itu
get
;d-
rar-
ia-
rto-
yvić
Kod
in-
ość
Przedstawiony w części Wartość specjalna sposób pozbycia się błędu sprawdzi się tylko wtedy, gdy prawdziwe będzie nasze pierwotne założenie, że klasa Tablica4 będzie przechowywała jedynie liczby nieujemne. Co jednak zrobić, gdy trzeba przechować liczby ujemne? Sposobów jest kilka (jeden z nich został przedstawiony w części Bez wyjątków), jednak dobrym pomysłem może być skorzystanie z tak zwanych wyjątków (patrz ramka poniżej). To specjalny mechanizm, który pozwala na obsługę sytuacji, jak sama nazwa wskazuje, wyjątkowych. Taką wyjątkową sytuacją może być właśnie przekazanie metodzie nieprawidłowego argumentu.
argumentem instrukcji throw może być niemal dowolny typ danych, umieszczamy w nim komunikat opisujący przyczynę błędu. Wykorzystamy go za chwilę w bloku catch.
Skoro metoda get klasy Tablicał generuje wyjątek, to instrukcja ją wywołująca powinna być ujęta w blok try. Dlatego też w programie korzystającym z najnowszej wersji klasy instrukcję pobierającą dane z obiektu tab
♦include <io8tream> jłinclude "Tablica4.ćpp"
ttfiing naaespace std;
int mąin(){
Tab.lica4 tab; int indeks, wynik;
cout « "Podaj indeks: cin » indeks:
int Tablica4::get(int indeks){ if(indeks >a 0 && indeks <= 3)< return tab[indeks];
•>:
else{
throw "Argument poza zakresem 41
i
(Tablica4 i:get)";
fP blad3/Tabllca4xpp"i
Aby w przedstawionym wcześniej programie zastosować technikę wyjątków, zmieniamy kod metody get klasy Tablicał na -------
Dzięki temu w przypadku wykrycia, że argument indeks przekracza dopuszczalny zakres, zostanie wykonana instrukcja throw 41. czyli zostanie zgłoszony wyjątek. Ponieważ
i
i Schemat obsługi wyjątków
Schemat obsługi sytuacji wyjątkowych (na przykład błędów) jest zawsze taki sam:
• w miejscu wykrycia błędu za pomocą Instrukcji tbrow zgłaszamy wyjątek (czynność tę nazywa się również wyrzucaniem wyjątku)
• instrukcje, które spodziewamy się, że mogą spowodować wystąpienie błędu, ujmujemy w blok try...catch o schematycznej postacię.
T
try{
//instrukcje mogące spowodować //powstanie wyjątku
}
catch (TypWyjątku obioktWyjątku);{
//instrukcjo wykonywane/ kiedy //powstanie wyjątek
>
argumentu indeks na pewno jest większa bądź równa 0, a zarazem mniejsza bądź równa 3 41. Jeśli oba warunki są spełnione, zwracana jesr wartość tablicy, a w przeciw-
class Tablica4{ private: int tab[4); public:
Tablica4 (); int get(int);
>;
Tablica4::Tablica4(){ tab[0] = 10; tob(1). = 20; tab(2] - 30; tab[3j‘ = 40;
}
int Tablica4::get(int indeks){ i£( indeks >= 0 && indeks <= 3) €1
return tab[indeks];
Ciso
return -1; €1 _,
*__m blad2/Tablića4.cpp |
try{
wynik = tab.get(indeks)j
j
S cout << "tab(" « indeks « j cout « wynik « endl;
/ 'ca tclffc o n sV “cfiVr opTs ff"'
{ cout << "Wystąpii błąd: i cout << endl;
________________
« opis;
oraz instrukcję wyświetlającą wynik umieszczamy w bloku try 43. Dodatkowo tworzymy blok catch €1, w którym umieszczamy kod obsługi błędu, czyli instrukcję powodującą wyświetlenie opisu błędu.
Jak będzie działał tak zmodyfikowany program? Jeżeli wprowadzony indeks będzie poprawny, instrukcje z bloku try 41 zostaną wykonane, a blok catch Cl zostanie pominięty. Jeśli jednak podczas wykonywania me-
Najepszym sposobem na obsługę błędów jest zastosowanie mechanizmu wyjątków. Jeśli jednak nie możemy lub z jakichś powodów nie chcemy stosować wyjątków, możemy skorzystać z innej techniki obsługi błędów. Do klasy można na przykład dodacpole error ® "i metodę isError • .^wracającą wartość tego pola. Dzięki temu metoda get może zwTacać dowolne wartości całkowite, a to, czy wystąpił błąd, czy nie, może być sprawdzane za pomocą wywołania isError %.
i
class Tablięa4{ privato: int tab( 4];
► bool error; public:
Tablica4(); int get(int); bool isEruror();
>?
Tablica4::Tablica4(){ tab(0) = 10; tab(l) = tab[2) = 30; tab(3] *
>
20;
40;
'bool Tablica4::isError(){ return error;
}
int Tablica4::get(int indeks)( £f(indeks>=0 && indeks<°3){ error = false; return tab[indeks];
>
olse{
error = true; return 0?
>
>
ID bład47TabHca4.cpp
i£(!tab.
.cout «
>
else{
cout <<;“Nieprawidłowy indeks tablicy" « endl;
}
sError()){ tabl" <<: indeks «
« wynik << endl;
i B bladą/prograin.cpp [
ca C:\WINI)OWS\system32\f:md.exe
C: \ !>proyrain.exe Podaj indeks: 256 Wystąpił blad: Argument poza <Tablica4::gct>
BI
tody get zostanie wygenerowany wyjątek, blok try zostanie przerwany, a sterowanie przekazane zostanie do bloku catch. Ważne jest, aby w nawiasie za słowem catch został wymieniony typ wyjątku generowany przez instrukcję throw. Ponieważ w naszym przypadku była to stała napisowa, odpowiednim typem jest const char*. W samym bloku catch można wykonać dowolne instrukcje.
nym przypadku - wartość -140. Tym samym metoda get będzie mogła sygnalizować otrzymanie niewłaściwego argumentu indeks.
Skoro jednak zmieniliśmy sposób działania metody get, nieco inny będzie też kod
łt.include <,ioBtream>
iinclude i'.Tablica4 .cpp" ^—*
using naoespacc std;
int main()<
Tablłća4 tab;
int indeks, wynik;
cout << "Podaj indeks:
cin >> indeks; €1 ^
i£( (wynik >= tab.get(indeks)) ! = -1){ cout « "tab(" « indeks « "J = M « wynik;
)
olso{
cout « "Nieprawidłov^ indeks tablicy";,
}
cout « endl;
>
| Pi bladż/programjcpp j
W prezentowanym programie ograniczamy się do wyświetlenia informacji o błędzie z opisu wygenerowanego przez instrukcję throw. A zatem kiedy po kompilacji i uruchomieniu programu podamy niewłaściwy indeks tabli-'ćy,'zobaczymy komunikat’4. Więcej o wyjątkach przeczytamy w następnej części kursu.
i
i Zadania do wykonania
Aby utrwalić zdobyte w kursie obiektowego C++ Informacje. Ekspert zachęca do samodzielnego wykonania czterech zadań. Ich treść znajdziemy na forum internetowym Eksperta (mvw.ks-ekspert.pl/lorum) w temacie Kurs obiektowego C++ (w dziale Programowanie). Poprawne roz-wiązania wraz z wyjaśnieniami znajdziemy w jednym z następnych numerów Eksperta.
programu korzystającego z klasy Tablica ®.
W celu ułatwienia testów, indeks tablicy jest wczytywany ze standardowego strumienia wejściowego dn i zapisywany w zmiennej pomocniczej indeks 41- Wywołanie metody get następuje natomiast w złożonej instrukcji warunkowej if d Wartość zwrócona przez get jest tu przypisywana zmiennej wynik oraz porównywana z -1. Jeśli więc wartością jest -1, wyświetlona zostanie informacja o nieprawidłowym indeksie •, jeżeli natomiast jest ona różna od -1, wyświetlona zostanie wartość pobrana z obiektu tab. ML Si
' C:\WINDOWS\syslom37\cmd.cxo
C:\! >prog»*an.cxe Podaj indeks: 256 Hicprat/idlouy indeks tablicy
C:\t >jłi*ogł*an.exe Podaj indeks: 2 tab m 30
ekspert
LUTY 2007 61