Les fonctions intéressées par les exceptions doivent les capter avec le mot clé catch comme on l'a vu ci-dessus. Elles peuvent alors effectuer tous les traitements d'erreurs que le C++ ne fera pas automatiquement. Ces traitements comprennent généralement le rétablissement de l'état des données manipulées par la fonction (dont, pour les fonctions membres d'une classe, les données membres de l'objet courant), ainsi que la libération des ressources non encapsulées dans des objets de classe de stockage automatique (par exemple, les fichiers ouverts, les connexions réseau, etc.).
Une fois ce travail effectué, elles peuvent, si elles le désirent, relancer l'exception, afin de permettre un traitement complémentaire par leur fonction appelante. Le parcours de l'exception s'arrêtera donc dès que l'erreur aura été complètement traitée. Bien entendu, il est également possible de lancer une autre exception que celle que l'on a reçue, comme ce peut être par exemple le cas si le traitement de l'erreur provoque lui-même une erreur.
Pour relancer l'exception en cours de traitement dans un gestionnaire d'exception, il faut utiliser le mot clé throw. La syntaxe est la suivante :
throw ;L'exception est alors relancée, avec comme valeur l'objet que le compilateur a construit en interne pour propager l'exception. Les gestionnaires d'exception peuvent donc modifier les paramètres des exceptions, s'ils les attrapent avec une référence.
Si, lorsqu'une exception se produit dans un bloc try,
il est impossible de trouver le bloc catch correspondant à la classe de cette
exception, il se produit une erreur d'exécution. La fonction prédéfinie
std::terminate
est alors appelée. Elle se contente d'appeler
une fonction de traitement de l'erreur, qui elle-même appelle la fonction abort
de la bibliothèque C. Cette fonction termine en catastrophe l'exécution du programme fautif en générant
une faute (les ressources allouées par le programme ne sont donc pas libérées, et des données peuvent
être perdues). Ce n'est généralement pas le comportement désiré, aussi est-il possible de le modifier
en changeant la fonction appelée par std::terminate
.
Pour cela, il faut utiliser la fonction
std::set_terminate
, qui attend en paramètre un pointeur sur la fonction
de traitement d'erreur, qui ne prend aucun paramètre et renvoie void. La valeur renvoyée
par std::set_terminate
est le pointeur sur la fonction de traitement
d'erreur précédente. std::terminate
et
std::set_terminate
sont déclaréee dans le fichier d'en-tête
exception.
Note : Comme leurs noms l'indiquent,
std::terminate
etstd::set_terminate
sont déclarées dans l'espace de nommage std::, qui est réservé pour tous les objets de la bibliothèque standard C++. Si vous ne voulez pas à avoir à utiliser systématiquement le préfixe std:: devant ces noms, vous devrez ajouter la ligne « using namespace std; » après avoir inclus l'en-tête exception. Vous obtiendrez de plus amples renseignements sur les espaces de nommage dans le Chapitre 11.
Exemple 9-2. Installation d'un gestionnaire d'exception avec set_terminate
#include <iostream> #include <exception> using namespace std; void mon_gestionnaire(void) { cout << "Exception non gérée reçue !" << endl; cout << "Je termine le programme proprement..." << endl; exit(-1); } int lance_exception(void) { throw 2; } int main(void) { set_terminate(&mon_gestionnaire); try { lance_exception(); } catch (double d) { cout << "Exception de type double reçue : " << d << endl; } return 0; }
Précédent | Sommaire | Suivant |
Les exceptions en C++ | Niveau supérieur | Liste des exceptions autorisées pour une fonction |