Za blokiem
try
można umieścić kilka następujących po sobie
bloków
catch. Jeśli w takiej sytuacji nastąpi zgłoszenie
wyjątku, to podczas poszukiwania odpowiedniej procedury obsługi
będzie sprawdzany typ wyjątków deklarowany w nagłówkach przez
kolejne bloki
catch. Jeśli (po ewentualnej konwersji niejawnej,
jak w poprzednim przykładzie) znaleziony zostanie odpowiedni typ, to ta
właśnie fraza
catch
zostanie użyta i na tym obsługa tego
wyjątku zakończy się: pozostałe bloki
catch
zostaną już
zignorowane, nawet jeśli jest wśród nich taki o bliższym dopasowaniu
typu parametru z typem wyjątku. Konwersje w górę są wykonywane tylko
dla argumentów obiektowych. Na przykład program
1. #include <iostream> 2. using namespace std; 3. 4. int main() { 5. try { 6. throw 7; 7. } 8. catch(double) { cout << "double" << endl; } 9. catch(int ) { cout << "int " << endl; } 10. }
Dla wyjątków typu obiektowego konwersja w górę będzie
jednak zastosowana
1. #include <iostream> 2. using namespace std; 3. 4. class A { }; 5. class B : public A { }; 6. 7. int main() { 8. try { 9. throw B(); 10. } 11. catch(A) { cout << "A" << endl; } 12. catch(B) { cout << "B" << endl; } 13. }
cpp> g++ -pedantic-errors -Wall -o hierob hierob.cpp hierob.cpp: In function `int main()': hierob.cpp:12: warning: exception of type `B' will be caught by earlier handler for `A' cpp> ./hierob AKompilator wypisał tu ostrzeżenie, bo w tym przykładzie druga fraza catch w ogóle nie jest osiągalna. To samo obowiązuje dla wyjątków wskaźnikowych; program
1. #include <iostream> 2. using namespace std; 3. 4. struct A { 5. const char* info() { return "A*"; } 6. }; 7. 8. struct B : A { 9. const char* info() { return "B*"; } 10. }; 11. 12. int main() 13. { 14. try { 15. throw new B; 16. } 17. catch(A* a) { cout << a->info() << endl; } 18. catch(B* b) { cout << b->info() << endl; } 19. }
cpp> g++ -pedantic-errors -Wall -o hier1 hier1.cpp hier1.cpp: In function `int main()': hier1.cpp:18: warning: exception of type `B*' will be caught by earlier handler for `A*' cpp> ./hier1 A*Tak więc, jeśli klasa B dziedziczy z A, wyjątek jest typu B (lub B*), a fraza catch deklaruje typ A (lub A* lub A&), to wyjątek zostanie wychwycony przez tę frazę, jeśli:
Czasem na samym końcu listy fraz catch umieszcza się taką frazę z trzema kropkami zamiast parametru
catch(...) { // ... }Oznacza ona „wyłap każdy wyjątek, niezależnie od jego typu”.
T.R. Werner, 21 lutego 2016; 20:17