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
A
Kompilator 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