Syntaxe de la gestion des exceptions C++ standard

De RAD Studio
Aller à : navigation, rechercher

Remonter à Gestion des exceptions C++ standard


La gestion des exceptions nécessite l'utilisation de trois mots clés : try, throw et catch. Le mot clé throw est utilisé pour générer une exception. Le bloc try contient des instructions susceptibles de déclencher des exceptions et il est suivi d'une ou plusieurs instructions catch. Chaque instruction catch gère un type d'exception spécifique.

Remarque : Les mots clés try, catch et throw ne sont pas autorisés dans les programmes C.

Le bloc try

Le bloc try contient une ou plusieurs instructions qui peuvent déclencher une exception. Un programme déclenche une exception en exécutant une instruction throw. L'instruction throw survient généralement au sein d'une fonction. Par exemple :

 void SetFieldValue(DF *dataField, int userValue)
 {
     if ((userValue < 0) || userValue > 10)
         throw EIntegerRange(0, 10, userValue);
     // ...
 }

Une autre partie du programme peut intercepter l’objet exception déclenché et le gérer en conséquence. Par exemple :

 try {
 	SetFieldValue(dataField, userValue);
 }
 catch (EIntegerRange &rangeErr) {
 	printf("Expected value between %d and %d, but got %d\n", rangeErr.min,
 		rangeErr.max, rangeErr.value);
 }

Dans l'exemple précédent, si la fonction SetFieldValue constate que ses paramètres d'entrée ne sont pas valides, elle peut déclencher une exception pour indiquer cette erreur. Si une exception est déclenchée, l'instruction printf est alors exécutée. Si aucune exception n'est déclenchée, l'instruction printf n'est pas exécutée.

Un bloc try spécifié par try doit être immédiatement suivi par le gestionnaire spécifié par catch. Le bloc try est une instruction qui spécifie le flux de contrôle au fur et à mesure que le programme s'exécute. Si une exception est déclenchée dans le bloc try, le contrôle du programme est transféré au gestionnaire d'exception approprié.

Le gestionnaire est un bloc de code conçu pour gérer l'exception. Le langage C++ nécessite qu'il y ait au moins un gestionnaire immédiatement après un bloc try. Le programme doit inclure un gestionnaire pour chaque exception susceptible d'être générée par le programme.

L'instruction throw

L'instruction throw peut déclencher divers types d'objets. Dans C++, les objets peuvent être généralement déclenchés par valeur, par référence ou par pointeur. Par exemple :

 // throw an object to be caught by value or reference
 throw EIntegerRange(0, 10, userValue);
 
 // throw an object to be caught by pointer
 throw new EIntegerRange(0, 10, userValue);

Remarque : Déclenchez les exceptions par valeur et interceptez les exceptions par référence pour empêcher les pertes de mémoire. Si vous interceptez une exception par pointeur, vous ne pourrez peut-être pas supprimer l'objet exception.

Remarque : Pour déclencher une exception par valeur, celle-ci doit avoir un constructeur de copie et un destructeur de copie publics.

De plus, l'instruction throw peut déclencher des types primitifs, tels que des entiers ou des pointeurs. Les deux exemples suivants montrent des fonctionnalités fournies dans un souci d'exhaustivité dans le système standard. Il est préférable de déclencher des exceptions plus descriptives. Dans certains cas particuliers, vous pouvez déclencher des types intégrés, par exemple des entiers. Enfin, il est préférable de ne pas déclencher des exceptions par pointeur.

 // throw an integer
 throw 1;
 
 // throw a char *
 throw "foo";

L'utilisation d'un objet exception au lieu d'une valeur primitive peut être plus efficace, car :

  • L'exception peut avoir une meilleure description.
  • L'exception peut être filtrée à l'aide du polymorphisme de classe.

Pour la plupart des cas, vous intercepterez les exceptions par référence, en particulier par référence const. Parfois, vous intercepterez avec précaution des objets par valeur. Les objets interceptés par valeur doivent être copiés avant d'être assignés au paramètre catch. Si un utilisateur fournit un constructeur de copie, celui-ci est appelé, ce qui peut altérer l'efficacité.

L'instruction catch

L'instruction catch se présente sous diverses formes. Les objets peuvent être interceptés par valeur, par référence ou par pointeur. En outre, des modificateurs const peuvent être appliqués au paramètre catch. Pour qu'un bloc try puisse intercepter plusieurs types d'exceptions différents, plusieurs instructions catch peuvent être ajoutées. Dans tous les cas, il doit y avoir une instruction catch pour chaque exception susceptible d'être déclenchée. Par exemple :

 try
     CommitChange(dataBase, recordMods);
 catch (const EIntegerRange &rangeErr)
     printf("Got an integer range exception");
 catch (const EFileError &fileErr)
     printf("Got a file I/O error");

Si la fonction CommitChange utilise plusieurs sous-systèmes qui peuvent déclencher différents types d'exceptions, vous pouvez gérer chaque type d'exception séparément. Avec plusieurs instructions catch pour une seule instruction try, vous pouvez avoir des gestionnaires pour chaque type d'exception.

Si un objet exception est dérivé d'une classe de base, vous pouvez ajouter des gestionnaires spécialisés pour certaines exceptions dérivées, mais aussi inclure un gestionnaire générique pour la classe de base. Pour ce faire, placez les instructions catch dans l'ordre dans lequel vous voulez qu'elles soient recherchées quand une exception est déclenchée. Par exemple, le code suivant gère d'abord EIntegerRange puis ERange, dont EIntegerRange est dérivée.

 try
     SetFieldValue(dataField, userValue);
 catch (const EIntegerRange &rangeErr)
     printf("Got an integer range exception");
 catch (const ERange &rangeErr)
     printf("Got a range exception");

Enfin, si vous voulez que votre gestionnaire intercepte toutes les exceptions susceptibles d'être déclenchées après le bloc try, utilisez la forme spéciale catch(...). Cette instruction indique au système de gestion des exceptions que le gestionnaire doit être invoqué pour toutes les exceptions. Par exemple :

 try
     SetFieldValue(dataField, userValue);
 catch (...)
     printf("Got an exception of some kind");

Voir aussi