86
Chapitre XI Chapitre XI Gestion des erreurs et exceptions

Chapitre XI Gestion des erreurs et exceptions. 2 La gestion des erreurs et exceptions De nombreux problèmes peuvent survenir pendant lexécution dun programme:

Embed Size (px)

Citation preview

Page 1: Chapitre XI Gestion des erreurs et exceptions. 2 La gestion des erreurs et exceptions De nombreux problèmes peuvent survenir pendant lexécution dun programme:

Chapitre XIChapitre XI

Gestion des erreurs et exceptions

Page 2: Chapitre XI Gestion des erreurs et exceptions. 2 La gestion des erreurs et exceptions De nombreux problèmes peuvent survenir pendant lexécution dun programme:

2

La gestion des erreurs et exceptions

De nombreux problèmes peuvent survenir pendant l’exécution d’un programme:- insuffisance de mémoire, disque plein,- perte d’un fichier, imprimante non branchée ou à court de papier,- saisie non valide d’une valeur,- une fonction ou une classe qui fonctionnent mal,- etc.

Rôle des programmeurs face à ces erreurs d’exécution:- prévoir ces erreurs,- une application étant construite à partir d’un enchaînement d’appels

de fonctions, toute fonction pouvant être confrontée à une erreur d’exécution, il devient nécessaire de pouvoir gérer les appels(les erreurs) en cascade de fonctions

- en informer l’utilisateur, sauver son travail et arrêter le programmede façon contrôlée,

- éventuellement, de mettre en œuvre des solutions de reprises et decorrection.

Page 3: Chapitre XI Gestion des erreurs et exceptions. 2 La gestion des erreurs et exceptions De nombreux problèmes peuvent survenir pendant lexécution dun programme:

3

Mise en œuvre de la gestion des erreurs d’exécution

Ignorer l’erreur

Utiliser une variable globale qui sera initialisée par la fonction provoquantl’erreur d’exécution.Le contenu de cette variable sera ensuite récupéré et traité par la fonction appelantede celle qui a entraîné l’erreur d’exécution.

Les variables globales n’offrent aucune garantie de sécurité. Cela signifie que toutes lesfonctions d’un programme peuvent y accéder sans restriction. **** à éviter ****

PROBLÈME RENCONTRÉ : le code qui détecte l’erreur ne peut rien fairepour sauver le travail de l’usager et quitter élégamment.

Programmation défensive

Prendre la décision de ne rien faire en cas de demande erronée.Ex. : Ne pas insérer un nouvel élément dans une pile pleine.

Dans certains cas, on ne peut ignorer l’erreur parce que l’opération ne peut êtrecomplétée. Ex. : lors d’un calcul.

Peut masquer des erreursimportantes de programmation

Supposer que les erreurs ne se produiront pas est une mauvaise approche.

Page 4: Chapitre XI Gestion des erreurs et exceptions. 2 La gestion des erreurs et exceptions De nombreux problèmes peuvent survenir pendant lexécution dun programme:

4

Mise en œuvre de la gestion des erreurs d’exécution

Imprimer un message d’erreur et / ou arrêter le programme

- Le code de traitement des erreurs est dispersé et imbriqué tout au long du code du système.

- Les erreurs sont gérées là où ces erreurs sont le plus susceptibles de se produire.

Avantage: En lisant le code, on peut voir le traitement d’erreur dans levoisinage immédiat du code et déterminer si une vérificationadéquate des erreurs a été mise en place.

Désavantage: Le code est « pollué » par le traitement d’erreurs.Cela rend le code plus difficile à comprendre et à maintenir.

Envisageable au cours de la phase de mise au point seulement.**** à éviter ****

Page 5: Chapitre XI Gestion des erreurs et exceptions. 2 La gestion des erreurs et exceptions De nombreux problèmes peuvent survenir pendant lexécution dun programme:

5

Mise en œuvre de la gestion des erreurs d’exécution

Arrêt de l’exécution grâce à des assertions

Ex. : Un message avisant l’usager que la mémoire disponible est insuffisantepermettrait à celui-ci de fermer des applications libérant de la mémoiresupplémentaire.

- Peut entraîner irritation et frustration.

- L’usager ne devrait recevoir que des messages ou des avertissements qui ont du sens à son niveau et sur lesquels il peut prendre action.

Une assertion est une expression booléenne évaluée lors de l’exécution.

Si l’expression est évaluée comme fausse, un message d’erreur de diagnosticest imprimé et le programme s’arrête.

Cela comprend généralement le texte de l’assertion ayant échoué ainsi quele nom de fichier et le numéro de ligne où apparaît l’assertion.

Page 6: Chapitre XI Gestion des erreurs et exceptions. 2 La gestion des erreurs et exceptions De nombreux problèmes peuvent survenir pendant lexécution dun programme:

6

Mise en œuvre de la gestion des erreurs d’exécution

Exemple : #include <cassert>. . .double valeur_future(double solde_initial, double p, int n){

assert(p >= 0); assert(n >= 0);return solde_initial * pow(1 + p / 100, n);

}

Inconvénient : Ce mécanisme peut être désactivé selon la volonté du programmeur.Si cela est fait pour des raisons de performance dans les programmesde production, on opte pour une politique à courte vue.

Plus important, mettre fin à l’exécution est souvent une méthode tropradicale pour répondre à une erreur. De nombreuses erreurs peuventêtre gérées si elles sont signalées de façon à ce qu’un programmeurpuisse les détecter et les analyser.

Page 7: Chapitre XI Gestion des erreurs et exceptions. 2 La gestion des erreurs et exceptions De nombreux problèmes peuvent survenir pendant lexécution dun programme:

7

Mise en œuvre de la gestion des erreurs d’exécution

Approche classique d’interception des erreurs: retour de code d’erreur

- des fonctions symbolisent les traitements à mettre en œuvre;

- ces fonctions renvoient des valeurs qui peuvent servir à déterminer le succèsou l’échec du traitement;

- on peut tester les valeurs de retour des fonctions et réagir en conséquenceaux erreurs d’exécution.

Page 8: Chapitre XI Gestion des erreurs et exceptions. 2 La gestion des erreurs et exceptions De nombreux problèmes peuvent survenir pendant lexécution dun programme:

Chapitre XI - Gestion des erreurs et exceptions

8

Utilisation des valeurs de Utilisation des valeurs de retour des fonctionsretour des fonctions

#include <iostream.h>int Fonction_1(………….){

……...// Retourne 0 si aucune erreur n’est détectée; un entier positif autrement.……..

}………...int Fonction_m(………….){

……...// Retourne 0 si aucune erreur n’est détectée; un entier positif autrement.……..

}

Page 9: Chapitre XI Gestion des erreurs et exceptions. 2 La gestion des erreurs et exceptions De nombreux problèmes peuvent survenir pendant lexécution dun programme:

Chapitre XI - Gestion des erreurs et exceptions

9

Utilisation des valeurs de Utilisation des valeurs de retour des fonctionsretour des fonctions

int main(){

……….// Appel de la fonction Fonction_i.// Si une erreur est détectée,

alors gérer cette erreur en lien avec la fonction Fonction_isinon appel de la fonction Fonction_j

si une erreur est détectée,alors gérer cette erreur en lien avec Fonction_jsinon ………..

……….}

Cela met en évidence l’architecture nécessaire à des appels de fonctions en cascadequi peuvent entraîner une erreur d’exécution.

Page 10: Chapitre XI Gestion des erreurs et exceptions. 2 La gestion des erreurs et exceptions De nombreux problèmes peuvent survenir pendant lexécution dun programme:

Chapitre XI - Gestion des erreurs et exceptions

10

Utilisation des valeurs de Utilisation des valeurs de retour des fonctionsretour des fonctions

Dans ce contexte, les appels de fonctions sont séparés par un test (if) qui permet devérifier la validité de l’appel précédent.

Architecture peu lisible et surtout très pénible à maintenir(if-else imbriqué qui alourdit l’écriture et la mise à jour du programme).

#include <iostream.h>enum Nom_des_fonctions {Fn_A, Fn_B};int Fonction_A(float v){

if (v < 0.0) return 1;if (v == 0.0) return 2;// Traitement.return 0;

}

int Fonction_B(char c){

if (c == ' ') return 1;if ((c < 'A') | (c > 'Z'))

return 3;// Traitement.return 0;

}

Page 11: Chapitre XI Gestion des erreurs et exceptions. 2 La gestion des erreurs et exceptions De nombreux problèmes peuvent survenir pendant lexécution dun programme:

Chapitre XI - Gestion des erreurs et exceptions

11

Utilisation des valeurs de Utilisation des valeurs de retour des fonctionsretour des fonctions

int Gestion_des_erreurs(Nom_des_fonctions Nom, int code_erreur){

if (Nom== Fn_A)switch(code_erreur){

case 0 : cout << "Parfait"; return 0;case 1 : cout<<"Erreur 1"; return 1; // Erreur gravecase 2 : cout << "Erreur 2"; return 0;default: cout << "Erreur"; return 0;

}else

Page 12: Chapitre XI Gestion des erreurs et exceptions. 2 La gestion des erreurs et exceptions De nombreux problèmes peuvent survenir pendant lexécution dun programme:

Chapitre XI - Gestion des erreurs et exceptions

12

Utilisation des valeurs de Utilisation des valeurs de retour des fonctionsretour des fonctions

if (Nom== Fn_B)switch(code_erreur){

case 0 : cout << "Parfait"; return 0;case 3 : cout <<"Erreur 3"; return 1; // Erreur gravedefault: cout << "Erreur"; return 0;

}else cout << "incomplet "; return 0;

}

Page 13: Chapitre XI Gestion des erreurs et exceptions. 2 La gestion des erreurs et exceptions De nombreux problèmes peuvent survenir pendant lexécution dun programme:

Chapitre XI - Gestion des erreurs et exceptions

13

Utilisation des valeurs de Utilisation des valeurs de retour des fonctionsretour des fonctions

int main(){

char C = ' ';float U = -3.2f;

if (Gestion_des_erreurs(Fn_A, Fonction_A(U))) return 1;if (Gestion_des_erreurs(Fn_B, Fonction_B(C))) return 1;

return 0;}

Un constructeur ne possédant pas de valeur de retour, cette fonction ne peut pasrenvoyer de valeur pour informer la fonction appelante qu’une erreur s’est produite.

Page 14: Chapitre XI Gestion des erreurs et exceptions. 2 La gestion des erreurs et exceptions De nombreux problèmes peuvent survenir pendant lexécution dun programme:

Chapitre XI - Gestion des erreurs et exceptions

14

Mécanisme des exceptionsMécanisme des exceptionsSolution fiable et standardisée de gestion d’erreurs d’exécution qui ne se fonde passur les valeurs de retour des fonctions.

- permet de capturer toutes les exceptions d’un type donné,

- permet de lever des exceptions et transférer le contrôle avec les informations pertinentes à une autre partie du code qui pourra gérer la situation correctement,

- en retirant le code de traitement des erreurs du « flot principal » d’exécution d’un programme, cela permet d’améliorer la lisibilité des programmes et faciliter leur maintenance.

- permet de gérer nativement les appels de fonctions en cascade,

- peut être utilisé dans le cas des constructeurs.

Page 15: Chapitre XI Gestion des erreurs et exceptions. 2 La gestion des erreurs et exceptions De nombreux problèmes peuvent survenir pendant lexécution dun programme:

Chapitre XI - Gestion des erreurs et exceptions

15

Mécanisme des exceptionsMécanisme des exceptions

Étapes de mise en œuvre:

(a) définir une classe d’exception(b) lancer l’exception(c) intercepter l’exception.

Note :(i) Le traitement des exceptions est conçu pour traiter les erreurs synchrones

(Ex. : division par zéro)mais, non, pour gérer des situations asynchrones

(Ex. : fin d’une opération d’E/S sur disque)lesquelles seront prises en compte par un traitement d’interruption.

(ii) Il est bien adapté aux systèmes construits sur la base de composants développés de manière distincte.

Page 16: Chapitre XI Gestion des erreurs et exceptions. 2 La gestion des erreurs et exceptions De nombreux problèmes peuvent survenir pendant lexécution dun programme:

Chapitre XI - Gestion des erreurs et exceptions

16

Définition d’une classe Définition d’une classe d’exceptiond’exception

Correspond à une classe C++ qui peut fournir des informations sur une erreur.

La définition d’une classe d’exception est obligatoire pour mettre en œuvre lemécanisme d’exception mais il n’existe aucune contrainte particulière pour définircette classe.

Ex.: class Erreur{

// Données et fonctions membres permettant de traiter les cas// d’exception.

// Ex. : Affichage d’un message d’erreur.}

Page 17: Chapitre XI Gestion des erreurs et exceptions. 2 La gestion des erreurs et exceptions De nombreux problèmes peuvent survenir pendant lexécution dun programme:

Chapitre XI - Gestion des erreurs et exceptions

17

Lancement d’une exceptionLancement d’une exception

Toute fonction qui souhaite lancer une exception doit utiliser un nouvel opérateur dulangage C++, throw.

Cet opérateur doit être suivi par un objet créé à partir d’une classe d’exception.

But de cet opérateur :° quitter la fonction qui l’utilise,° informer la fonction appelante qu’une exception a été générée.

Voir à la prochaine étapecomment la fonction appelantepeut intercepter cette exception

Ex.: void Positive(int v){

if (v<0) {Erreur exc;throw exc;

}// Traitement propre à cette fonction réalisé uniquement si l’exception// n’est pas lancée.

}

Page 18: Chapitre XI Gestion des erreurs et exceptions. 2 La gestion des erreurs et exceptions De nombreux problèmes peuvent survenir pendant lexécution dun programme:

18

Lancement d’une exceptionLancement d’une exceptionSyntaxe simplifiée:

void Positive(int v){

if (v<0) throw Erreur();// Traitement propre à cette fonction réalisé uniquement si l’exception// n’est pas lancée.

}

Réalise sur la même lignela création de l’objet detype Erreur et l’envoi de

cet objet avec throw.

Un objet d’exception est créé sans lui attribuer de nom.

Avantageux seulement si vous n’avez pas besoin d’appeler des fonctions membresde la classe d’exception.

Dans ce cas, le simple fait de savoir qu’une exception d’un type donné a été lancéepeut fournir une information suffisante pour que le gestionnaire catch puisseeffectuer son travail correctement.

Page 19: Chapitre XI Gestion des erreurs et exceptions. 2 La gestion des erreurs et exceptions De nombreux problèmes peuvent survenir pendant lexécution dun programme:

Chapitre XI - Gestion des erreurs et exceptions

19

Lancement d’une exceptionLancement d’une exceptionSpécification d’exception d’une fonction

Optionnel pour une fonction susceptible d’envoyer une ou plusieurs exceptions,il s’agit d’indiquer dans sa déclaration juste après la liste de ses arguments lesexceptions susceptibles d’être lancées.

Ex.: float Racine_carree(float v) throw(Negatif){

// Traitement}

Cette fonction est capablede lancer des exceptionscorrespondant à la classe

Negatif.Rôle :- permet au compilateur de contrôler la liste des

exceptions envoyées par une fonction,- permettre aux programmeurs d’identifier très

rapidement la liste des exceptions pouvant êtrelancées par une fonction.

Autrement,le compilateur

générera unavertissement.

Page 20: Chapitre XI Gestion des erreurs et exceptions. 2 La gestion des erreurs et exceptions De nombreux problèmes peuvent survenir pendant lexécution dun programme:

Chapitre XI - Gestion des erreurs et exceptions

20

Interception d’une exceptionInterception d’une exception

L’interception d’une exception n’est pas obligatoire.Par contre, une exception envoyée et non interceptée provoque la fin de l’exécutiondu programme.

Pour intercepter une exception, le C++ fournit le bloc try et un ou plusieurs blocscatch:

try{

// Traitement renfermant des appels de fonctions pouvant générer// des exceptions.

}catch (Classe_Exception Ex){

// Ce bloc s’exécute pour une exception de type Classe_Exception.}…….

Page 21: Chapitre XI Gestion des erreurs et exceptions. 2 La gestion des erreurs et exceptions De nombreux problèmes peuvent survenir pendant lexécution dun programme:

Chapitre XI - Gestion des erreurs et exceptions

21

Interception d’une exceptionInterception d’une exception

catch (...){

// Ce bloc s’exécute pour tous les autres types d’exceptions.// Il faut toujours mettre catch(…) à la fin de la liste des gestionnaires// qui suivent un bloc try, sans quoi, cela empêche l’exécution des// blocs catch qui le suivent.

}Pour intercepter les exceptions susceptibles d’être envoyées par certaines fonctions,vous devez appeler ces fonctions dans le cadre d’un bloc try délimité par desaccolades.

Après le bloc try, il faut obligatoirement spécifier au moins un bloc catch.

Les exceptions ne peuvent être lancées que de l’intérieur de blocs try.Une exception lancée de l’extérieur d’un bloc try provoque la fin du programme.

Page 22: Chapitre XI Gestion des erreurs et exceptions. 2 La gestion des erreurs et exceptions De nombreux problèmes peuvent survenir pendant lexécution dun programme:

22

Interception d’une exceptionInterception d’une exception

Lorsqu’une exception est envoyée par une des fonctions appelées dans le bloc try,le mécanisme d’exception entraîne :

Tous les objets créés dans le bloc try sont détruits.Le programme sort du bloc try juste après la fonction qui a entraîné l’exceptionet n’exécute pas les instructions situées après cette fonction.

Le C++ exécute dans l’ordre,soit le bloc catch correspondant à l’exception interceptée s’il existe,soit le bloc catch(…).

Si aucune de ces conditions n’est remplie, cela entraînela fin d’exécution du programme.

Dans le cas de l’interception d’une classe d’exception précise, le bloc catch récupèredirectement une copie de l’objet créé et renvoyé par l’opérateur throw.

Au lancement, l’exception est capturée par le plus proche gestionnaired’exceptions (p/r au bloc try depuis lequel l’exception a été lancée) qui spécifieun type approprié.

Page 23: Chapitre XI Gestion des erreurs et exceptions. 2 La gestion des erreurs et exceptions De nombreux problèmes peuvent survenir pendant lexécution dun programme:

Chapitre XI - Gestion des erreurs et exceptions

23

Interception d’une exceptionInterception d’une exception

Si un des blocs catch a été utilisé, à la fin de son exécution, le programmecontinue à exécuter les instructions situées après le dernier bloc catch associé àce bloc try.

Il est impossible de retourner au point de lancement en plaçant une instructionreturn dans un gestionnaire catch.

Un tel return provoque le retour à la fonction qui a appelé la fonction contenantle bloc catch.

Si, à l’exécution, le code du bloc try ne lance pas d’exception, alors tous les gestion-naires catch qui suivent immédiatement le bloc try sont évités et l’exécution reprendà la première ligne de code suivant les gestionnaires catch.

Page 24: Chapitre XI Gestion des erreurs et exceptions. 2 La gestion des erreurs et exceptions De nombreux problèmes peuvent survenir pendant lexécution dun programme:

Chapitre XI - Gestion des erreurs et exceptions

24

Interception d’une exceptionInterception d’une exception

Que doit-on mettre en œuvre dans un bloc catch?

Tout dépend du niveau d’erreur de l’exception interceptée :

* arrêter le programme avec ou sans message utilisateur,

* corriger le problème avec ou sans message utilisateur,

* uniquement informer l’utilisateur.

le programmeur l’administrateur du site informatique

perte d’un fichier, d’un disque, etc.mauvaise saisie à l’écran,instabilité numérique, etc.

libellé affiché àl’écranlancement d’uneimpressionécriture dans un fichier logetc.

Page 25: Chapitre XI Gestion des erreurs et exceptions. 2 La gestion des erreurs et exceptions De nombreux problèmes peuvent survenir pendant lexécution dun programme:

Chapitre XI - Gestion des erreurs et exceptions

25

Interception d’une exceptionInterception d’une exception

Que doit-on mettre en œuvre dans un bloc catch?

Lors de la capture d’une exception, il se peut que des ressources qui avaient étéallouées n’aient pas encore été relâchées dans le bloc try.

Le gestionnaire catch doit, si possible, les libérer.

De même, le gestionnaire catch doit fermer tout fichier ouvert dans le bloc try.

Page 26: Chapitre XI Gestion des erreurs et exceptions. 2 La gestion des erreurs et exceptions De nombreux problèmes peuvent survenir pendant lexécution dun programme:

Chapitre XI - Gestion des erreurs et exceptions

26

Valeurs lancées et interceptéesValeurs lancées et interceptées

Vous pouvez lancer n’importe quel type de valeur, primitive ou objet.

Exemple : throw 3;

try{

. . .}catch (int a){

. . .}

Ce n’est pas une très bonne idée.Cela n’offre pas suffisammentd’informations pour expliquer l’erreur.

Note : Les conversions implicites, comme celles de int en double ou de char *en string ne sont pas effectuées lorsqu’une valeur est lancée.

Page 27: Chapitre XI Gestion des erreurs et exceptions. 2 La gestion des erreurs et exceptions De nombreux problèmes peuvent survenir pendant lexécution dun programme:

Chapitre XI - Gestion des erreurs et exceptions

27

ExempleExemple

class syndicat{/* Le président d'un syndicat local possède l'information suivante

sur ses membres (dont le nombre ne dépassera jamais 100) :- le numéro d'employé (lequel est une identification unique

de l'employé correspondant à un nombre de 4 chiffresdont le premier est 6),

- son nom, - son prénom, - son adresse,- son traitement annuel- sa cotisation syndicale annuelle (entre 0 et 2%).Chaque composante de la classe syndicat renferme les caractéris-tiques d'un membre. */

Fichier Syndicat.h

Page 28: Chapitre XI Gestion des erreurs et exceptions. 2 La gestion des erreurs et exceptions De nombreux problèmes peuvent survenir pendant lexécution dun programme:

Chapitre XI - Gestion des erreurs et exceptions

28

ExempleExemple

protected:struct employe{

int numero_employe;char nom[20+1], prenom[20+1], adresse[40+1];float traitement_annuel;float cotisation_annuelle;

} ensemble_membres[100];

int Nombre_de_membres; /* Renferme le nombre de syndiqués.*/

Page 29: Chapitre XI Gestion des erreurs et exceptions. 2 La gestion des erreurs et exceptions De nombreux problèmes peuvent survenir pendant lexécution dun programme:

Chapitre XI - Gestion des erreurs et exceptions

29

ExempleExemple

public:syndicat();/* Permet de créer un syndicat avec aucun membre.

Pré - Nil.Post - Le syndicat est créé avec aucun membre.*/

float Calcule_cotisation_annuelle_moyenne();

/* Fournit la moyenne des cotisations annuelles des membres.Pré - Le syndicat a déjà été créé et possède au moins

un membre.Post - Retourne la moyenne des cotisations annuelles.*/

Page 30: Chapitre XI Gestion des erreurs et exceptions. 2 La gestion des erreurs et exceptions De nombreux problèmes peuvent survenir pendant lexécution dun programme:

Chapitre XI - Gestion des erreurs et exceptions

30

ExempleExemple

void Inserer_nouveau_membre( int numero_employe,char * nom, char * prenom, char * adresse,float traitement_annuel,float cotisation_annuelle);

/* Permet d'ajouter un nouveau membre syndiqué dont lescaractéristiques sont passées en paramètres.Pré - Le syndicat a déjà été créé et le nombre d'employés

est moindre que 100. L'employé ayant ce numéron'est pas syndiqué jusqu'à maintenant.

Post - Le nouveau membre dont les caractéristiques sont passéesen paramètres fait maintenant partie du syndicat. */

};

Page 31: Chapitre XI Gestion des erreurs et exceptions. 2 La gestion des erreurs et exceptions De nombreux problèmes peuvent survenir pendant lexécution dun programme:

Chapitre XI - Gestion des erreurs et exceptions

31

ExempleExemple

class Erreur{

public:int code_erreur;int numero_employe;float cotisation_annuelle;

};

Page 32: Chapitre XI Gestion des erreurs et exceptions. 2 La gestion des erreurs et exceptions De nombreux problèmes peuvent survenir pendant lexécution dun programme:

Chapitre XI - Gestion des erreurs et exceptions

32

ExempleExemple

#include <string.h>#include "syndicat.h"

syndicat::syndicat(){

Nombre_de_membres = 0;}

Fichier Syndicat.cpp

Page 33: Chapitre XI Gestion des erreurs et exceptions. 2 La gestion des erreurs et exceptions De nombreux problèmes peuvent survenir pendant lexécution dun programme:

Chapitre XI - Gestion des erreurs et exceptions

33

ExempleExemple

float syndicat::Calcule_cotisation_annuelle_moyenne(){

Erreur Exc;float somme = 0.0f;if (Nombre_de_membres == 0) { Exc.code_erreur = 1;

throw Exc;};

for (int i = 0; i < Nombre_de_membres; i++)somme += ensemble_membres[i].cotisation_annuelle;

return somme / Nombre_de_membres;}

Page 34: Chapitre XI Gestion des erreurs et exceptions. 2 La gestion des erreurs et exceptions De nombreux problèmes peuvent survenir pendant lexécution dun programme:

Chapitre XI - Gestion des erreurs et exceptions

34

ExempleExemple

void syndicat::Inserer_nouveau_membre( int numero_employe,char * nom, char * prenom, char * adresse,float traitement_annuel,float cotisation_annuelle)

{Erreur Exc;if (Nombre_de_membres == 100) { Exc.code_erreur =2;

throw Exc;};

Page 35: Chapitre XI Gestion des erreurs et exceptions. 2 La gestion des erreurs et exceptions De nombreux problèmes peuvent survenir pendant lexécution dun programme:

Chapitre XI - Gestion des erreurs et exceptions

35

ExempleExemple

for (int i = 0; i < Nombre_de_membres; i++)if (ensemble_membres[i].numero_employe == numero_employe)

{ Exc.code_erreur = 3;throw Exc;

};

if ((numero_employe < 6000) | (numero_employe > 6999)){

Exc.code_erreur = 4;Exc.numero_employe = numero_employe;throw Exc;

};

Page 36: Chapitre XI Gestion des erreurs et exceptions. 2 La gestion des erreurs et exceptions De nombreux problèmes peuvent survenir pendant lexécution dun programme:

Chapitre XI - Gestion des erreurs et exceptions

36

ExempleExemple

if((cotisation_annuelle < 0) | (cotisation_annuelle > 2)){

Exc.code_erreur = 5;Exc.cotisation_annuelle = cotisation_annuelle;throw Exc;

};

Page 37: Chapitre XI Gestion des erreurs et exceptions. 2 La gestion des erreurs et exceptions De nombreux problèmes peuvent survenir pendant lexécution dun programme:

Chapitre XI - Gestion des erreurs et exceptions

37

ExempleExemple

ensemble_membres[Nombre_de_membres].numero_employe =numero_employe;

strcpy(ensemble_membres[Nombre_de_membres].nom, nom);strcpy(ensemble_membres[Nombre_de_membres].prenom, prenom);strcpy(ensemble_membres[Nombre_de_membres].adresse, adresse);ensemble_membres[Nombre_de_membres].traitement_annuel =

traitement_annuel;ensemble_membres[Nombre_de_membres].cotisation_annuelle =

cotisation_annuelle;Nombre_de_membres += 1;

}

Page 38: Chapitre XI Gestion des erreurs et exceptions. 2 La gestion des erreurs et exceptions De nombreux problèmes peuvent survenir pendant lexécution dun programme:

Chapitre XI - Gestion des erreurs et exceptions

38

ExempleExemple

#include <iostream.h>#include "syndicat.h"void main(){

syndicat S;

Fichier Application.cpp

Page 39: Chapitre XI Gestion des erreurs et exceptions. 2 La gestion des erreurs et exceptions De nombreux problèmes peuvent survenir pendant lexécution dun programme:

Chapitre XI - Gestion des erreurs et exceptions

39

ExempleExemple

try{ S.Inserer_nouveau_membre( 6423, "Poulin", "Luc",

"4356 rue Dupre, Quebec",53500.0f, 1.97f);

S.Inserer_nouveau_membre( 6677, "Fortin", "Diane", "4356 rue Duluth, Ste_Foy",53900.0f, 0.35f);

S.Inserer_nouveau_membre( 6820, "Leduc", "Pierre", "56 Lapointe, Cap_Rouge",75700.0f, 2.35f);

cout << S.Calcule_cotisation_annuelle_moyenne();}

Page 40: Chapitre XI Gestion des erreurs et exceptions. 2 La gestion des erreurs et exceptions De nombreux problèmes peuvent survenir pendant lexécution dun programme:

Chapitre XI - Gestion des erreurs et exceptions

40

ExempleExemplecatch(Erreur Exc){

switch(Exc.code_erreur){case 1 : cout << "Il faut au moins un employe"; break;case 2 : cout << "Il y a deja 100 membres."; break;case 3 : cout << "Cet employe est deja membre."; break;case 4 : cout << "Matricule invalide :   "

<< Exc.numero_employe; break;case 5 : cout << "cotisation invalide : "

<< Exc.cotisation_annuelle; break;}

}}

Page 41: Chapitre XI Gestion des erreurs et exceptions. 2 La gestion des erreurs et exceptions De nombreux problèmes peuvent survenir pendant lexécution dun programme:

Chapitre XI - Gestion des erreurs et exceptions

41

Mise en œuvre de plusieurs Mise en œuvre de plusieurs classes d’exceptionclasses d’exception

Fichier Syndicat.hLe fichier n’a pas changé à l ’exception de la classe Erreur qui a été remplacée par :

class Erreur_Numero_employe{

private:int numero_employe;

public:Erreur_Numero_employe(int Numero_employe);void Afficher();

};

Page 42: Chapitre XI Gestion des erreurs et exceptions. 2 La gestion des erreurs et exceptions De nombreux problèmes peuvent survenir pendant lexécution dun programme:

Chapitre XI - Gestion des erreurs et exceptions

42

Mise en œuvre de plusieurs Mise en œuvre de plusieurs classes d’exceptionclasses d’exception

Fichier Syndicat.h

class Erreur_Cotisation{

private: float cotisation_annuelle;public: Erreur_Cotisation(float cotisation);

void Afficher();};class Erreur_Nombre_de_membres{

private: int nombre_de_membres;public: Erreur_Nombre_de_membres

(int Nombre_de_membres);void Afficher();

};

Page 43: Chapitre XI Gestion des erreurs et exceptions. 2 La gestion des erreurs et exceptions De nombreux problèmes peuvent survenir pendant lexécution dun programme:

Chapitre XI - Gestion des erreurs et exceptions

43

Mise en œuvre de plusieurs Mise en œuvre de plusieurs classes d’exceptionclasses d’exceptionFichier Syndicat.cpp

Erreur_Numero_employe::Erreur_Numero_employe(int Numero_employe)

{numero_employe = Numero_employe;

}Erreur_Nombre_de_membres::Erreur_Nombre_de_membres

(int Nombre_de_membres){

nombre_de_membres = Nombre_de_membres;}Erreur_Cotisation::Erreur_Cotisation(float cotisation){

cotisation_annuelle = cotisation;}

Page 44: Chapitre XI Gestion des erreurs et exceptions. 2 La gestion des erreurs et exceptions De nombreux problèmes peuvent survenir pendant lexécution dun programme:

Chapitre XI - Gestion des erreurs et exceptions

44

Mise en œuvre de plusieurs Mise en œuvre de plusieurs classes d’exceptionclasses d’exception

Fichier Syndicat.cpp

void Erreur_Numero_employe::Afficher(){

cout << "Mauvais numero d'employe: " << numero_employe;}void Erreur_Cotisation:: Afficher(){

cout << "Mauvais taux de cotisation : " << cotisation_annuelle;}void Erreur_Nombre_de_membres:: Afficher(){

cout << "Le nombre de membres est inadequat : " << nombre_de_membres;

}

Page 45: Chapitre XI Gestion des erreurs et exceptions. 2 La gestion des erreurs et exceptions De nombreux problèmes peuvent survenir pendant lexécution dun programme:

Chapitre XI - Gestion des erreurs et exceptions

45

Mise en œuvre de plusieurs Mise en œuvre de plusieurs classes d’exceptionclasses d’exception

Fichier Syndicat.cpp

float syndicat::Calcule_cotisation_annuelle_moyenne(){

float somme = 0.0f;if (Nombre_de_membres == 0)throw Erreur_Nombre_de_membres(Nombre_de_membres);

for (int i = 0; i < Nombre_de_membres; i++)somme += ensemble_membres[i].cotisation_annuelle;

return somme / Nombre_de_membres;}

Page 46: Chapitre XI Gestion des erreurs et exceptions. 2 La gestion des erreurs et exceptions De nombreux problèmes peuvent survenir pendant lexécution dun programme:

Chapitre XI - Gestion des erreurs et exceptions

46

Mise en œuvre de plusieurs Mise en œuvre de plusieurs classes d’exceptionclasses d’exception

Fichier Syndicat.cpp

void syndicat::Inserer_nouveau_membre( int numero_employe,

char * nom, char * prenom, char *adresse,float traitement_annuel, float cotisation_annuelle)

{if (Nombre_de_membres == 100) throw Erreur_Nombre_de_membres(Nombre_de_membres);for (int i = 0; i < Nombre_de_membres; i++)if (ensemble_membres[i].numero_employe == numero_employe)

throw Erreur_Numero_employe(numero_employe);if ((numero_employe < 6000) | (numero_employe > 6999))

throw Erreur_Numero_employe(numero_employe);

Page 47: Chapitre XI Gestion des erreurs et exceptions. 2 La gestion des erreurs et exceptions De nombreux problèmes peuvent survenir pendant lexécution dun programme:

Chapitre XI - Gestion des erreurs et exceptions

47

Mise en œuvre de plusieurs Mise en œuvre de plusieurs classes d’exceptionclasses d’exception

Fichier Syndicat.cpp

if((cotisation_annuelle < 0) | (cotisation_annuelle > 2)) throw Erreur_Cotisation(cotisation_annuelle);

// Ajout d’un membre (idem à précédemment)}

Page 48: Chapitre XI Gestion des erreurs et exceptions. 2 La gestion des erreurs et exceptions De nombreux problèmes peuvent survenir pendant lexécution dun programme:

Chapitre XI - Gestion des erreurs et exceptions

48

Mise en œuvre de plusieurs Mise en œuvre de plusieurs classes d’exceptionclasses d’exception

Fichier Application.cpp

#include <iostream.h>#include "syndicat.h"

void main(){

syndicat S;

Page 49: Chapitre XI Gestion des erreurs et exceptions. 2 La gestion des erreurs et exceptions De nombreux problèmes peuvent survenir pendant lexécution dun programme:

Chapitre XI - Gestion des erreurs et exceptions

49

Mise en œuvre de plusieurs Mise en œuvre de plusieurs classes d’exceptionclasses d’exception

Fichier Application.cpp

try{

S.Inserer_nouveau_membre( 6423, "Poulin", "Luc", "4356 rue Dupre, Quebec",53500.0f, 1.97f);

S.Inserer_nouveau_membre( 6677, "Fortin", "Diane", "4356 rue Duluth, Sainte_Foy",53900.0f, 0.35f);

S.Inserer_nouveau_membre( 6423, "Leduc", "Pierre", "56 rue Lapointe, Cap_Rouge",75700.0f, 1.35f);

cout << S.Calcule_cotisation_annuelle_moyenne();}

Page 50: Chapitre XI Gestion des erreurs et exceptions. 2 La gestion des erreurs et exceptions De nombreux problèmes peuvent survenir pendant lexécution dun programme:

Chapitre XI - Gestion des erreurs et exceptions

50

Mise en œuvre de plusieurs Mise en œuvre de plusieurs classes d’exceptionclasses d’exception

Fichier Application.cpp

catch(Erreur_Numero_employe Exc){

Exc.Afficher();}catch(Erreur_Cotisation Exc){

Exc.Afficher();}catch(Erreur_Nombre_de_membres Exc){

Exc.Afficher();}

}

Page 51: Chapitre XI Gestion des erreurs et exceptions. 2 La gestion des erreurs et exceptions De nombreux problèmes peuvent survenir pendant lexécution dun programme:

Chapitre XI - Gestion des erreurs et exceptions

51

Mise en œuvre de plusieurs Mise en œuvre de plusieurs classes d’exceptionclasses d’exception

Bref, les exceptions sont symbolisées par des classes pour lesquelles vous pouvezintégrer des données et fonctions membres qui permettent de définir une gestiond’erreur appropriée.

Nous pouvons utiliser l’héritage et le polymorphisme pour définir de véritableshiérarchies de classes spécialisées dans le traitement des erreurs.

La classe de base de cette arborescence permettra de regrouper les comportementscommuns à un groupe d’exceptions tout en laissant la possibilité de spécialiser lesclasses dérivées.

Page 52: Chapitre XI Gestion des erreurs et exceptions. 2 La gestion des erreurs et exceptions De nombreux problèmes peuvent survenir pendant lexécution dun programme:

Chapitre XI - Gestion des erreurs et exceptions

52

Mise en œuvre de plusieurs Mise en œuvre de plusieurs classes d’exceptionclasses d’exception

Quand une concordance exacte se produira-t-elle ?

Le type du paramètre du gestionnaire catch correspond exactement au type de l’objetlancé si :

- ils sont effectivement du même type; ou

- le type du paramètre du gestionnaire catch est une classe de base publique de la classe de l’objet lancé; ou

- le paramètre du gestionnaire est un type de référence ou de pointeur d’une classe de base et l’objet lancé est une référence ou un pointeur d’une classe dérivée de cette classe de base. ou

- le gestionnaire catch est de la forme catch(…).

Page 53: Chapitre XI Gestion des erreurs et exceptions. 2 La gestion des erreurs et exceptions De nombreux problèmes peuvent survenir pendant lexécution dun programme:

Chapitre XI - Gestion des erreurs et exceptions

53

Mise en œuvre de plusieurs Mise en œuvre de plusieurs classes d’exceptionclasses d’exception

Note :

(i) La correspondance de type doit être exacte. Aucune conversion n’est effectuée lorsde la recherche d’un gestionnaire, à l’exception des conversions de classe dérivéeen classe de base.

(ii) Placer un gestionnaire d’exceptions avec un type d’argument void * avant lesgestionnaires d’exceptions utilisant d’autres types de pointeurs provoque uneerreur de logique. Pourquoi ?

(iii) Il est possible de lancer des objets const. Dans ce cas, le type de l’argument dugestionnaire catch doit également être déclaré comme const.

Page 54: Chapitre XI Gestion des erreurs et exceptions. 2 La gestion des erreurs et exceptions De nombreux problèmes peuvent survenir pendant lexécution dun programme:

Chapitre XI - Gestion des erreurs et exceptions

54

Hiérarchie de classes Hiérarchie de classes d’exceptiond’exception

class Erreur{

public: virtual void Afficher() = 0;};class Erreur_Numero_employe : public Erreur{

private:int numero_employe;

public:Erreur_Numero_employe(int Numero_employe);virtual void Afficher();

};

Fichier Syndicat.h

La classe de base Erreur est introduite : Fonction virtuelle purequi devra être redéfiniedans toutes les classes dérivéesde la classe abstraite Erreur.

Page 55: Chapitre XI Gestion des erreurs et exceptions. 2 La gestion des erreurs et exceptions De nombreux problèmes peuvent survenir pendant lexécution dun programme:

Chapitre XI - Gestion des erreurs et exceptions

55

Hiérarchie de classes Hiérarchie de classes d’exceptiond’exception

class Erreur_Cotisation : public Erreur{

private: float cotisation_annuelle;public: Erreur_Cotisation(float cotisation);

virtual void Afficher();};class Erreur_Nombre_de_membres : public Erreur{

private: int nombre_de_membres;public: Erreur_Nombre_de_membres

(int Nombre_de_membres);virtual void Afficher();

};

Fichier Syndicat.h

Page 56: Chapitre XI Gestion des erreurs et exceptions. 2 La gestion des erreurs et exceptions De nombreux problèmes peuvent survenir pendant lexécution dun programme:

Chapitre XI - Gestion des erreurs et exceptions

56

Hiérarchie de classes Hiérarchie de classes d’exceptiond’exception

Fichier Syndicat.cpp

Un seul changement: les objets d’exception sont créés dynamiquement avec l’opérateurnew et c’est l’adresse d’un objet qui est envoyée avec l’opérateur throw.

float syndicat::Calcule_cotisation_annuelle_moyenne(){

float somme = 0.0f;if (Nombre_de_membres == 0)

throw new Erreur_Nombre_de_membres(Nombre_de_membres);

for (int i = 0; i < Nombre_de_membres; i++)somme += ensemble_membres[i].cotisation_annuelle;

return somme / Nombre_de_membres;}

Page 57: Chapitre XI Gestion des erreurs et exceptions. 2 La gestion des erreurs et exceptions De nombreux problèmes peuvent survenir pendant lexécution dun programme:

Chapitre XI - Gestion des erreurs et exceptions

57

Hiérarchie de classes Hiérarchie de classes d’exceptiond’exception

Fichier Syndicat.cpp

void syndicat::Inserer_nouveau_membre( int numero_employe, char * nom, char * prenom, char * adresse,

float traitement_annuel, float cotisation_annuelle){

if (Nombre_de_membres == 100)throw new Erreur_Nombre_de_membres(Nombre_de_membres);

for (int i = 0; i < Nombre_de_membres; i++)if (ensemble_membres[i].numero_employe == numero_employe)

throw new Erreur_Numero_employe(numero_employe);if ((numero_employe < 6000) | (numero_employe > 6999))

throw new Erreur_Numero_employe(numero_employe);

Page 58: Chapitre XI Gestion des erreurs et exceptions. 2 La gestion des erreurs et exceptions De nombreux problèmes peuvent survenir pendant lexécution dun programme:

Chapitre XI - Gestion des erreurs et exceptions

58

Hiérarchie de classes Hiérarchie de classes d’exceptiond’exception

Fichier Syndicat.cpp

if((cotisation_annuelle < 0) | (cotisation_annuelle > 2))throw new Erreur_Cotisation(cotisation_annuelle);

// Ajout d’un membre (idem à précédemment)}

Page 59: Chapitre XI Gestion des erreurs et exceptions. 2 La gestion des erreurs et exceptions De nombreux problèmes peuvent survenir pendant lexécution dun programme:

Chapitre XI - Gestion des erreurs et exceptions

59

Hiérarchie de classes Hiérarchie de classes d’exceptiond’exception

Fichier Application.cpp

#include <iostream.h>#include "syndicat.h"

void main(){

syndicat S;

Page 60: Chapitre XI Gestion des erreurs et exceptions. 2 La gestion des erreurs et exceptions De nombreux problèmes peuvent survenir pendant lexécution dun programme:

Chapitre XI - Gestion des erreurs et exceptions

60

Hiérarchie de classes Hiérarchie de classes d’exceptiond’exception

Fichier Application.cpp

try{

S.Inserer_nouveau_membre( 6423, "Poulin", "Luc", "4356 rue Dupre, Quebec",53500.0f, 1.97f);

S.Inserer_nouveau_membre( 6677, "Fortin", "Diane", "4356 rue Duluth, Sainte_Foy",53900.0f, 0.35f);

S.Inserer_nouveau_membre( 6423, "Leduc", "Pierre", "56 rue Lapointe, Cap_Rouge",75700.0f, 1.35f);

cout << S.Calcule_cotisation_annuelle_moyenne();}

Page 61: Chapitre XI Gestion des erreurs et exceptions. 2 La gestion des erreurs et exceptions De nombreux problèmes peuvent survenir pendant lexécution dun programme:

Chapitre XI - Gestion des erreurs et exceptions

61

Hiérarchie de classes Hiérarchie de classes d’exceptiond’exception

Fichier Application.cpp

catch(Erreur * pExc){

pExc -> Afficher();delete pExc;

}

}

un seul bloc catchpour intercepterles 3 exceptions.

Ce bloc, défini pour un pointeur vers la classe de base, s’appliqueraaux adresses des objets des classes dérivées.

La fonction virtuelle Afficher sera appelée par rapport au type d’objetafin d’afficher le message d’erreur adéquat.

L’objet d’exception doit être détruit.

Page 62: Chapitre XI Gestion des erreurs et exceptions. 2 La gestion des erreurs et exceptions De nombreux problèmes peuvent survenir pendant lexécution dun programme:

Chapitre XI - Gestion des erreurs et exceptions

62

Hiérarchie de classes Hiérarchie de classes d’exceptiond’exception

Pour bénéficier des avantages d’une arborescence de classes d’exceptions, il n’est pas nécessaire de créer les objets en dynamique.

Contrairement à précédemment, on peut continuer à créer ces objets en statique au moment de lancer l’exception avec l’opérateur throw.

if((cotisation_annuelle < 0) | (cotisation_annuelle > 2))throw Erreur_Cotisation(cotisation_annuelle);

Pour bénéficier du polymorphisme, il sera nécessaire de définir un bloc catch pourintercepter une référence à la classe de base de la hiérarchie.

catch(Erreur & Exc){

Exc.Afficher();}

Il n ’est plus nécessaire de détruire

explicitement les objetsd’exception créés.

Page 63: Chapitre XI Gestion des erreurs et exceptions. 2 La gestion des erreurs et exceptions De nombreux problèmes peuvent survenir pendant lexécution dun programme:

63

Hiérarchie de classes Hiérarchie de classes d’exceptiond’exception

Il se peut que plusieurs gestionnaires d’exceptions fournissent une correspondance acceptable au type de l’exception lancée.

Ex. :(i) Un gestionnaire catch(…) interceptant toutes les exceptionspeut être présent.

(ii) Il est possible qu’un objet dérivé d’une classe soit capturé parun gestionnaire spécifiant le type dérivé ou par des gestionnairesspécifiant le type de n’importe quelle classe de base de cetteclasse dérivée.

Dans ce cas, le 1e gestionnaire d’exceptions qui concorde avec le type d’exception lancé est exécuté.

Si plusieurs gestionnaires correspondent et si chacun d’eux gère l’exception de manière différente, alors l’ordre des gestionnaires définit la manière dont l’exception est traitée.

Page 64: Chapitre XI Gestion des erreurs et exceptions. 2 La gestion des erreurs et exceptions De nombreux problèmes peuvent survenir pendant lexécution dun programme:

64

Hiérarchie de classes Hiérarchie de classes d’exceptiond’exception

Note :

Placer un catch qui capture un objet de classe de base avant un catch qui capture unobjet d’une classe dérivée de cette classe de base est une erreur de logique. Pourquoi ?

Page 65: Chapitre XI Gestion des erreurs et exceptions. 2 La gestion des erreurs et exceptions De nombreux problèmes peuvent survenir pendant lexécution dun programme:

65

Comment écrire un gestionnaire Comment écrire un gestionnaire d’exceptions (bloc catch)?d’exceptions (bloc catch)?

(a) Ausculter précisément une erreur et décider d’appeler terminate(fin anormale du programme).

(b) Convertir un type d’exceptions en un autre en lançant une exception différente.

(c) Effectuer toute restauration utile et reprendre l’exécution après le derniergestionnaire d’exceptions.

(d) Étudier la situation ayant causé l’erreur, retirer la cause de l’erreur et tenter unnouvel appel à la fonction d’où émanait l’exception.

(e) Retourner une éventuelle valeur d’état à leur environnement.

Page 66: Chapitre XI Gestion des erreurs et exceptions. 2 La gestion des erreurs et exceptions De nombreux problèmes peuvent survenir pendant lexécution dun programme:

66

Comment écrire un gestionnaire Comment écrire un gestionnaire d’exceptions (bloc catch)?d’exceptions (bloc catch)?

(f) Relancer une exception.

Le gestionnaire qui intercepte une exception peut décider qu’il ne peut la traiter. Il peut alors relancer l’exception à l’aide de l’instruction throw;

Un tel throw, sans argument, relance la même exception.

Une exception relancée est détectée par le bloc try le plus proche qui entoure legestionnaire en cours et est traitée par le gestionnaire d’exceptions listé par ce bloc trypériphérique.

Note :

Un gestionnaire catch peut lui-même découvrir une erreur et lancer une exception.Une telle exception ne sera pas traitée par les gestionnaires mais, si possible, par ungestionnaire catch associé au prochain bloc try qui entoure celui en cours.

Page 67: Chapitre XI Gestion des erreurs et exceptions. 2 La gestion des erreurs et exceptions De nombreux problèmes peuvent survenir pendant lexécution dun programme:

67

Relancer une exception : Relancer une exception : exempleexemple

#include <iostream>#include <exception>using namespace std;void lancerException() throw(exception){

// lancer une exception et l’intercepter immédiatement.try { cout << "Fonction lancerException\n";

throw exception();}

catch(exception e){

cout << "Exception geree dans la fonction lancerException\n";throw; // Relancer l’exception pour traitement ultérieur.

} cout << "Ceci ne devrait pas s’afficher.\n";

}

la classe exception de la bibliothèque demodèles standard définie dans le fichier en-tête<exception>.

Page 68: Chapitre XI Gestion des erreurs et exceptions. 2 La gestion des erreurs et exceptions De nombreux problèmes peuvent survenir pendant lexécution dun programme:

68

Relancer une exception : Relancer une exception : exempleexemple

void main(){

try { lancerException(); cout << "Ceci ne devrait pas s’afficher.\n";

}catch(exception e){

cout << "Exception gérée dans la fonction main\n";} cout << "Le contrôle du programme continue apres capture dans main.\n";

<< endl;} Fonction lancerException

Exception geree dans la fonction lancerExceptionException geree dans la fonction mainLe contrôle du programme continue apres capture dans main.

Page 69: Chapitre XI Gestion des erreurs et exceptions. 2 La gestion des erreurs et exceptions De nombreux problèmes peuvent survenir pendant lexécution dun programme:

69

Spécification d’exceptions Spécification d’exceptions dans une fonctiondans une fonction

Nous pouvons spécifier une liste d’exceptions qu’une fonction peut lancer.

Exemple : int g(float m) throw(a, b, c){

// Corps de la fonction.}

Une fonction peut lancer les exceptions indiquées ou des types dérivés.

Si une exception qui ne fait pas partie de la liste est lancée, un appel à la fonctionunexpected (« inattendue ») est effectué.

Si la liste est vide, i.e.int g(float m) throw(){

…} alors la fonction ne lancera aucune exception.

Si la fonction le faisait, un appel à lafonction unexpected serait effectué.

Page 70: Chapitre XI Gestion des erreurs et exceptions. 2 La gestion des erreurs et exceptions De nombreux problèmes peuvent survenir pendant lexécution dun programme:

70

Spécification d’exceptions Spécification d’exceptions dans une fonctiondans une fonction

Une fonction sans spécification d’exceptions peut lancer n’importe quelle exception.

int g(float m){

…}

Traitement d’exceptions inattendues (fonction unexpected) :

- Par défaut, c’est la fonction terminate.

- Une autre fonction peut être spécifiée grâce à :set_unexpected(pointeur vers une fonction).

Page 71: Chapitre XI Gestion des erreurs et exceptions. 2 La gestion des erreurs et exceptions De nombreux problèmes peuvent survenir pendant lexécution dun programme:

71

Dépilage d’une pileDépilage d’une pile

Lorsqu’une exception est lancée mais pas capturée dans une portée particulière,la pile d’appels de fonctions est dépilée et la capture de l’exception est tentée dans lebloc try-catch extérieur le plus proche.

Lorsque la pile d’appels de fonctions est dépilée, la fonction dans laquelle l’exceptionn’a pas été interceptée est telle que toutes ses variables locales sont détruites et lecontrôle revient au point où la fonction a été appelée.

- Si ce point du programme se trouve dans un bloc try, la capture dans un bloc catch associé est tentée.

- Si ce point du programme n’est pas dans un bloc try ou si l’exception n’y est pas interceptée, le dépilage des appels de fonctions est effectué une fois encore.

- Si l’exception n’est pas interceptée dans le programme, la fonction terminate est appelée.

Page 72: Chapitre XI Gestion des erreurs et exceptions. 2 La gestion des erreurs et exceptions De nombreux problèmes peuvent survenir pendant lexécution dun programme:

72

Dépilage d’une pile (exemple)Dépilage d’une pile (exemple)

#include <iostream>#include <stdexcept>using namespace std;void fonction3() throw(runtime_error){ throw runtime_error("erreur à l’exécution de la fonction3"); }

void fonction2() throw(runtime_error){ fonction3(); }

void fonction1() throw(runtime_error){ fonction2(); }

void main(){ try { fonction1(); }

catch(runtime_error e){ cout << "Exception rencontrée: "  << endl << e.what() << endl;}

}

Exception rencontrée:erreur à l’exécution de la fonction3

dépile

Page 73: Chapitre XI Gestion des erreurs et exceptions. 2 La gestion des erreurs et exceptions De nombreux problèmes peuvent survenir pendant lexécution dun programme:

73

Hiérarchie de classes d’exceptions de la bibliothèque Hiérarchie de classes d’exceptions de la bibliothèque

standard: fichier en-tête <exception>standard: fichier en-tête <exception>

Projet de norme de C++

Offre le service what() : émet un message d’erreur approprié.

Plusieurs classes dérivées de la classe exception :runtime_error, logic_error, invalid_argument, length_error,out_of_range, overflow_error, underflow_error, ...

La hiérarchie d’exceptions standard est conçue pour servir de point de départ.

On peut donc lancer des exceptions standard ou nos propres exceptions.

Pour capturer toutes les exceptions qui peuvent être lancées dans un bloc try,utilisez catch(…), et non catch(exception e).

Page 74: Chapitre XI Gestion des erreurs et exceptions. 2 La gestion des erreurs et exceptions De nombreux problèmes peuvent survenir pendant lexécution dun programme:

74

Hiérarchie des types d’exceptionsHiérarchie des types d’exceptionsde la bibliothèque standardde la bibliothèque standard

Page 75: Chapitre XI Gestion des erreurs et exceptions. 2 La gestion des erreurs et exceptions De nombreux problèmes peuvent survenir pendant lexécution dun programme:

75

Hiérarchie de classes d’exceptions de la bibliothèque Hiérarchie de classes d’exceptions de la bibliothèque

standard: fichier en-tête <exception>standard: fichier en-tête <exception> Exemple I : On peut créer des objets de ces classes standards.

#include <cmath>#include <stdexcept>using namespace std;double valeur_future(double solde_initial, double p, int n){

if (p < 0 || n < 0){

logic_error description("Le parametre valeur_future est illegal.");throw description;

};return solde_initial * pow(1 + p / 100, n);

}. . .try { . . . }catch (logic_error & e){ cout << " Erreur de traitement "   << e.what() << "\n"; }

Page 76: Chapitre XI Gestion des erreurs et exceptions. 2 La gestion des erreurs et exceptions De nombreux problèmes peuvent survenir pendant lexécution dun programme:

76

Hiérarchie de classes d’exceptions de la bibliothèque Hiérarchie de classes d’exceptions de la bibliothèque

standard: fichier en-tête <exception>standard: fichier en-tête <exception> Exemple II : On avertit l’usager d’un problème et on offre une chance de

recommencer avec d’autres entrées.

void main(){

bool plus = true;while (plus){

try{

code}catch (logic_error & e){

cout << "Une erreur de logique est survenue : "<< e.what() << "\n"<< "Recommencer ? (o / n)";

string entree;getline(cin, entree);if (entree == "n") plus = false;

}}

}

Page 77: Chapitre XI Gestion des erreurs et exceptions. 2 La gestion des erreurs et exceptions De nombreux problèmes peuvent survenir pendant lexécution dun programme:

77

Hiérarchie de classes d’exceptions de la bibliothèque Hiérarchie de classes d’exceptions de la bibliothèque

standard: fichier en-tête <exception>standard: fichier en-tête <exception> Exemple III : On emploie l’héritage pour définir nos propres types d’exception

comme catégories plus spécialisées des classes standards.

class ErreurValeurFuture : public logic_error{

public :ErreurValeurFuture(string raison);

};ErreurValeurFuture::ErreurValeurFuture(string raison)

: logic_error(raison){

. . .}

La fonction valeur_future peut maintenant lancer un objet ErreurValeurFuture :

if (p < 0 || n < 0) throw ErreurValeurFuture("parametre illegal");

Un objet de ErreurValeurFuture dérivée de logic_error peut être capturé avec uneclasse catch(logic_error & e).

Page 78: Chapitre XI Gestion des erreurs et exceptions. 2 La gestion des erreurs et exceptions De nombreux problèmes peuvent survenir pendant lexécution dun programme:

78

Hiérarchie de classes d’exceptions de la bibliothèque Hiérarchie de classes d’exceptions de la bibliothèque

standard: fichier en-tête <exception>standard: fichier en-tête <exception> Vous pouvez aussi fournir une clause catch(ErreurValeurFuture & e) ne capturantque les objets de ErreurValeurFuture et non les autres erreurs de logique.

Vous pouvez même faire les deux :try{

code}catch (ErreurValeurFuture & e){

gestionnaire 1}catch (logic_error & e){

gestionnaire 2}. . .

L’ordre est important.

Page 79: Chapitre XI Gestion des erreurs et exceptions. 2 La gestion des erreurs et exceptions De nombreux problèmes peuvent survenir pendant lexécution dun programme:

79

Construction d’un programme testConstruction d’un programme testBut : Ce test permet de s’assurer qu’une classe se comporte telle que spécifiée;

Permet de détecter toute anomalie le plus tôt possible.

Ce test utilise systématiquement l’interface publique de la classe.

Ce test doit être appliqué autant de fois que l’on veut.

Ce test doit fournir un rapport d’exécution extrêmement simple.

succèsou

échec

Toutes les méthodes publiques de la classe doivent être testées.

Les tests pour chaque méthode doivent être indépendants les uns des autrespour éviter les effets de bord.Si on teste une méthode A, on doit se concentrer sur le test de A et prendrepour acquis que les autres méthodes fonctionnent correctement.

Page 80: Chapitre XI Gestion des erreurs et exceptions. 2 La gestion des erreurs et exceptions De nombreux problèmes peuvent survenir pendant lexécution dun programme:

Chapitre XI - Gestion des erreurs et exceptions

80

Exemple d’un programme testExemple d’un programme test

Les fichiers « syndicat.h » et « syndicat.cpp » demeurent intacts.

Le programme d’application précédent est remplacé par le programme test suivant.

#include <iostream.h>#include "Syndicat Hierarchie.h"#include <cassert>void test_syndicat(){

// Immédiatement après la création d'un nouveau syndicat, le nombre de// membres du syndicat doit être égale à 0.syndicat S;assert(S.Nombre_de_membres_du_syndicat() == 0);

}

assert(<condition logique>) Lorsque la condition logique est fausse, uneexception est lancée.

Page 81: Chapitre XI Gestion des erreurs et exceptions. 2 La gestion des erreurs et exceptions De nombreux problèmes peuvent survenir pendant lexécution dun programme:

Chapitre XI - Gestion des erreurs et exceptions

81

Exemple d’un programme testExemple d’un programme test

void test_Calcule_cotisation_annuelle_moyenne(){

// La fonction testée doit retourner la cotisation annuelle moyenne.syndicat S;S.Inserer_nouveau_membre( 6423, "Poulin", "Luc",

"4356 rue Dupre, Quebec",53500.0f, 1.99f);

S.Inserer_nouveau_membre( 6677, "Fortin", "Diane", "4356 rue Duluth, Sainte_Foy",53900.0f, 0.35f);

S.Inserer_nouveau_membre( 6433, "Leduc", "Pierre", "56 rue Lapointe, Cap_Rouge",75700.0f, 1.35f);

assert(S.Calcule_cotisation_annuelle_moyenne() == 1.23f);

Page 82: Chapitre XI Gestion des erreurs et exceptions. 2 La gestion des erreurs et exceptions De nombreux problèmes peuvent survenir pendant lexécution dun programme:

Chapitre XI - Gestion des erreurs et exceptions

82

Exemple d’un programme testExemple d’un programme test

// Le syndicat doit posséder au moins un membre.

bool CasInvalide = false;try{

syndicat V;

cout << V.Calcule_cotisation_annuelle_moyenne();}catch(...){

CasInvalide = true;}assert(CasInvalide);

}

Page 83: Chapitre XI Gestion des erreurs et exceptions. 2 La gestion des erreurs et exceptions De nombreux problèmes peuvent survenir pendant lexécution dun programme:

Chapitre XI - Gestion des erreurs et exceptions

83

Exemple d’un programme testExemple d’un programme test

void test_Nombre_de_membres_du_syndicat(){

// La fonction testée doit retourner le nombre de membres du syndicat.syndicat S;S.Inserer_nouveau_membre( 6423, "Poulin", "Luc",

"4356 rue Dupre, Quebec",53500.0f, 1.99f);

S.Inserer_nouveau_membre( 6677, "Fortin", "Diane", "4356 rue Duluth, Sainte_Foy",53900.0f, 0.35f);

S.Inserer_nouveau_membre( 6433, "Leduc", "Pierre", "56 rue Lapointe, Cap_Rouge",75700.0f, 1.35f);

assert(S.Nombre_de_membres_du_syndicat() == 3);}

Page 84: Chapitre XI Gestion des erreurs et exceptions. 2 La gestion des erreurs et exceptions De nombreux problèmes peuvent survenir pendant lexécution dun programme:

84

Exemple d’un programme testExemple d’un programme testvoid test_Inserer_nouveau_membre(){ // L'employé à insérer n'était pas déjà syndiqué.

bool CasInvalide = false;try{ syndicat S;

S.Inserer_nouveau_membre( 6423, "Poulin", "Luc", "4356 rue Dupre, Quebec",53500.0f, 1.99f);

S.Inserer_nouveau_membre( 6423, "Poulin", "Luc", "4356 rue Dupre, Quebec",53500.0f, 1.99f);

}catch(...){ CasInvalide = true; }assert(CasInvalide);

}

Page 85: Chapitre XI Gestion des erreurs et exceptions. 2 La gestion des erreurs et exceptions De nombreux problèmes peuvent survenir pendant lexécution dun programme:

Chapitre XI - Gestion des erreurs et exceptions

85

Exemple d’un programme testExemple d’un programme testvoid main(){

try{

test_syndicat();test_Calcule_cotisation_annuelle_moyenne();test_Nombre_de_membres_du_syndicat();test_Inserer_nouveau_membre();cout << "Ce test pour la classe syndicat est reussi. "  << endl;

}catch(...){

cout << "Le test pour la classe syndicat a echoue. "   << endl;}

}

Page 86: Chapitre XI Gestion des erreurs et exceptions. 2 La gestion des erreurs et exceptions De nombreux problèmes peuvent survenir pendant lexécution dun programme:

Chapitre XI - Gestion des erreurs et exceptions

86

Programme testProgramme test

FIN FIN

Le programme test appelle une fonction de test pour chaque méthode publiquede la classe à tester.Dans chacun de ces tests, on doit clairement documenter ce qu’on veut tester.

On doit utiliser des assertions pour vérifier le comportement de la classe vue del’extérieur.