22.5 Specyfikacje wyjątków

Definiując funkcję można jawnie wypecyfikować, jakiego typu wyjątki mogą zostać zgłoszone, a nie obsłużone podczas jej wykonywania. Robi się to poprzez podanie frazy throw po liście parametrów, a przed średnikiem (w deklaracji) lub ciałem funkcji (w definicji). We frazie tej należy podać w nawiasach listę oddzielonych przecinkami typów wyjątków, jakie mogą być zgłoszone, a nie obsłużone:

                      // deklaracja
       int fun(double) throw(std::bad_alloc, PozaZakresem);
       // ...
                      // definicja
       int fun(double x) throw(std::bad_alloc, PozaZakresem) {
           // ...
       }
Fraza ta musi wystąpić zarówno w deklaracji, jak i w definicji funkcji.

Jeśli taka fraza została podana dla metody wirtualnej, to wszystkie wersje przesłaniające tę metodę w klasach pochodnych mogą tylko „odejmować” niektóre typy — te, dla których same zapewnią obsługę. Nie można natomiast w klasach potomnych rozszerzać listy możliwych typów wyjątków metody wirtualnej.

Brak specyfikacji wyjątków w definicji funkcji jest równoważny podaniu

       throw( wszystkie_mozliwe_typy )
natomiast fraza z pustą listą
       throw()
oznacza, że w danej funkcji nie powinny zdarzyć się żadne nie obsłużone sytuacje wyjątkowe.

Jeśli funkcja może zgłosić nieobsłużony wyjątek typu nie wymienionego na liście specyfikacji, to program i tak się skompiluje, choć dobry kompilator powinien wypisać stosowne ostrzeżenia. Ta niekonsekwencja spowodowana jest koniecznością zachowania zgodności z istniejącymi programami i bibliotekami.

Jeśli podczas wykonywania programu w pewnej funkcji nastąpi nieobsłużone zgłoszenie wyjątku typu nie wymienionego w jej specyfikacji wyjątków, to program kończy się wywołaniem funkcji unexpected, która z kolei woła funkcję terminate. Tak jak można, za pomocą set_terminate, „podstawić” własną wersję funkcji terminate, tak za pomocą set_unexpected można określić inną funkcję, która ma pełnić rolę funkcji unexpected.

T.R. Werner, 21 lutego 2016; 20:17