Académique Documents
Professionnel Documents
Culture Documents
Achref El Mouelhi
elmouelhi.achref@gmail.com
C++
Exception ?
H I ©
C’est une erreur qui se produit pendant l’ex
U L de notre
Eécution
programme
L MO
Une exception dans e
r E
unfprogramme implique généralement son
c h
©A
arrêt d’exécution
C++
H I ©
EL
Repérer les blocs pouvant lancer une exception
U
O
LM
Capturer l’exception correspondante
r e f E
Afficher un message relatif à cette exception
ch
©A
Continuer l’exécution
H I ©
U EL
O
f E LM
ch r e
©A
C++
C++
Commençons par modifier la fonction division pour lancer une exception si y = 0
}
throw string("division / 0");
H I ©
return x / y;
UEL
}
O
f E LM
ch r e
©A
C++
Commençons par modifier la fonction division pour lancer une exception si y = 0
}
throw string("division / 0");
H I ©
return x / y;
UEL
}
O
f E LM
ch r e
Explication
©A
Si y = 0, on arrête l’exécution de cette fonction
Mais elle lance une exception et envoie un message de type string dont le contenu est
division / 0
Ajoutons les deux blocs try et catch dans l’appel de la fonction dans le main
int main()
{
int i = 3, j = 0;
try
{
cout << division(i, j) << endl;
}
catch (string const &msg)
{
}
cout << "Erreur : " << msg << endl;
H I ©
EL
cout << "Message à afficher si l'exception est capturée";
U
return 0;
}
O
f E LM
ch r e
©A
Ajoutons les deux blocs try et catch dans l’appel de la fonction dans le main
int main()
{
int i = 3, j = 0;
try
{
cout << division(i, j) << endl;
}
catch (string const &msg)
{
}
cout << "Erreur : " << msg << endl;
H I ©
EL
cout << "Message à afficher si l'exception est capturée";
U
return 0;
}
O
f E LM
En exécutant
ch r e
Erreur : division / 0
©A
Message à afficher si l’exception est capturée
Ajoutons les deux blocs try et catch dans l’appel de la fonction dans le main
int main()
{
int i = 3, j = 0;
try
{
cout << division(i, j) << endl;
}
catch (string const &msg)
{
}
cout << "Erreur : " << msg << endl;
H I ©
EL
cout << "Message à afficher si l'exception est capturée";
U
return 0;
}
O
f E LM
En exécutant
ch r e
Erreur : division / 0
©A
Message à afficher si l’exception est capturée
Explication
C++
Remarque
H I ©
EL
Pour l’exemple précédent, on a géré les exceptions en
transmettant des chaı̂nes de caractère
M OU
Il serait plus pertinent de E
f L une classe exception et lui
définir
envoyer les param e
r pour qu’elle construise le message
chètres
© A
d’erreur adéquat
#ifndef ARITHMETICEXCEPTION_H
#define ARITHMETICEXCEPTION_H
#include <string>
H I ©
EL
class ArithmeticException
{
public:
O U
second){};
f E LM
ArithmeticException(int first, int second) : first(first), second(
ch r e
string getMessage() { return "Problème de division : " + to_string(
©A
first) + " / " + to_string(second); };
private:
int first;
int second;
};
#endif
C++
Modifions maintenant la fonction division()
r e f E
ch
©A
C++
Modifions maintenant la fonction division()
r e f E
ch
©A
Remarque (pour les développeurs Java, C#...)
Pour tester
int main()
{
int i = 3, j = 0;
try
{
cout << division(i, j) << endl;
}
catch (ArithmeticException &e)
H I ©
{
UEL
cout << e.getMessage() << endl;
O
}
f E LM
cout << "Message à afficher si l'exception est capturée";
}
return 0;
ch r e
©A
Pour tester
int main()
{
int i = 3, j = 0;
try
{
cout << division(i, j) << endl;
}
catch (ArithmeticException &e)
H I ©
{
UEL
cout << e.getMessage() << endl;
O
}
f E LM
cout << "Message à afficher si l'exception est capturée";
}
return 0;
ch r e
©A
Le résultat est
Problème de division : 3 / 0
Message à afficher si l’exception est capturée
C++
H I ©
EL
On peut définir une deuxième condition
O U
LM
Les deux entiers à utiliser dans la fonction division ne doivent pas
r e f E
dépasser une borne max (par exemple 5) sinon on lève une exception.
ch
©A
#ifndef UPPERBOUNDEXCEPTION_H
#define UPPERBOUNDEXCEPTION_H
#include <string>
class UpperBoundException
H I ©
{
UEL
public:
O
LM
UpperBoundException(int param) : param(param) {}
string getMessage()
{
r e f E
ch
return "Valeur max autorisée (5) dépassée, valeur saisie : " +
} ©A
to_string(param);
private:
int param;
};
#endif
C++
Modifions la fonction division()
r e
throw UpperBoundException(y);f E
}
ch
if (y == 0)
{ ©A
throw ArithmeticException(x, y);
}
return x / y;
}
int main()
{
int i = 6, j = 0;
try
{
cout << division(i, j) << endl;
H I ©
EL
}
catch (UpperBoundException & e)
O U
LM
{
}
cout << e.getMessage() << endl;
r e f E
ch
©A
catch (ArithmeticException & e)
{
cout << e.getMessage() << endl;
}
cout << "Message à afficher si l'exception est capturée";
return 0;
}
C++
Remarques
H I ©
EL
On peut à la fin par exemple ajouter une exception plus générale
U
O
catch (exception & e) pour capturer les exceptions
standards
f E LM
ch r e
Pour capturer le reste, on peut aussi ajouter en dernier catch (
... )
©A
Il faut toujours partir du plus spécifique et aller vers le plus général
C++
H I ©
EL
Question : comment fusionner tous ces blocs de catch en un seul ?
O U
Créer une classe mère abstraite BaseException pour toutes les
classes d’exception précédentes
f E LM
ch r e
©A
C++
Code de BaseException
#ifndef BASEEXCEPTION_H
#define BASEEXCEPTION_H
#include <string>
H I ©
UEL
using namespace std; O
f E LM
class BaseException
ch r e
{
public: ©A
virtual string getMessage() = 0;
};
#endif
C++
#ifndef ARITHMETICEXCEPTION_H
#define ARITHMETICEXCEPTION_H
#include <string>
#include "BaseException.h"
H I ©
EL
using namespace std;
string getMessage()
r e E
ArithmeticException(int first, int second) : first(first), second(second){};
f
ch
{
©A
return "Problème de division : " + to_string(first) + " / " + to_string(second);
};
private:
int first;
int second;
};
#endif
C++
Et UpperBoundException
#ifndef UPPERBOUNDEXCEPTION_H
#define UPPERBOUNDEXCEPTION_H
#include <string>
#include "BaseException.h"
H I ©
EL
using namespace std;
string getMessage()
r e f E
UpperBoundException(int param) : param(param) {}
{
ch
©A
return "Valeur max autorisée (5) dépassée, valeur saisie : " + to_string(param);
}
private:
int param;
};
#endif
C++
Le nouveau main()
int main()
{
int i = 6, j = 0;
try
H I ©
{
UEL
cout << division(i, j) << endl;
O
}
f E LM
catch (BaseException &e)
{
ch r e
} ©A
cout << e.getMessage() << endl;
C++
Exceptions standards
H I ©
EL
Plusieurs exceptions prédéfinies dans le namespace std
U
O
LM
Pour les capturer, on peut utiliser la classe prédéfinie exception
r e f E
La méthode what() de cette classe retourne le motif de
ch
©A
l’exception
C++
Exemple d’échec de conversion de string en int
int main()
{
string str = "bonjour";
try
{
}
int i = stoi(str);
H I ©
EL
catch (exception & e)
{
cout << "Erreur : " << e.what() << endl;
O U
LM
}
cout << "Message à afficher si l'exception est capturée";
}
return 0;
r e f E
ch
©A
C++
Exemple d’échec de conversion de string en int
int main()
{
string str = "bonjour";
try
{
}
int i = stoi(str);
H I ©
EL
catch (exception & e)
{
cout << "Erreur : " << e.what() << endl;
O U
LM
}
cout << "Message à afficher si l'exception est capturée";
}
return 0;
r e f E
ch
©A
En exécutant
Erreur : stoi
Message à afficher si l’exception est capturée
C++
Exemple de problème de création de vecteur
int main()
{
try
{
vector<int> vecteur (500000000);
}
catch (exception & e)
H I ©
{
cout << "Erreur : " << e.what() << endl;
UEL
}
O
LM
cout << "Message à afficher si l'exception est capturée";
E
return 0;
}
r e f
ch
©A
C++
Exemple de problème de création de vecteur
int main()
{
try
{
vector<int> vecteur (500000000);
}
catch (exception & e)
H I ©
{
cout << "Erreur : " << e.what() << endl;
UEL
}
O
LM
cout << "Message à afficher si l'exception est capturée";
E
return 0;
}
r e f
ch
©A
En exécutant
C++
Exceptions
C++
Exceptions
Pour vérifier des choses qui ne devraient jamais arriver, on utilise les assertions.
C++
Assertions ?
Permettent de vérifier si une condition est vraie
H I ©
Si oui, le programme continue.
UEL
O
LM
Sinon, le programme s’arrête et indique la source d’erreur.
r e f E
ch
©A
C++
Assertions ?
Permettent de vérifier si une condition est vraie
H I ©
Si oui, le programme continue.
UEL
O
LM
Sinon, le programme s’arrête et indique la source d’erreur.
r e f E
ch
©A
Pour utiliser les assertions, on ajoute
#include <cassert>
C++
Considérons le code suivant
int main()
{
int i;
cout << "saisissez un entier positif " << endl;
H I ©
EL
// saisissez une valeur négative
cin >> i;
O U
LM
if (i % 3 == 0)
{
r e f E
cout << i << " est divisible par 3" << endl;
}
ch
else
{ ©A
assert(i % 3 == 1 || i % 3 == 2);
cout << i << " n'est pas divisible par 3" << endl;
}
}
C++
H I ©
EL
Remarque
O U
Dans le cas où l’utilisateur saisit une valeur négative, nous nous
E LM
rendrons compte que ce cas n’est pas compris dans le else.
f
ch r e
©A