-
C’est un mécanisme pour gérer proprement les erreurs à l’exécution.
-
Quand une fonction rencontre une erreur :
- elle “lance” une exception
- la fonction courante est terminée immédiatement
- les fonctions appelantes sont aussi terminées jusqu’à trouver un morceau de code qui sache gérer l’exception
- si aucun bloc de code ne traite l’exception, le programme se termine.
-
Les erreurs "classiques" à traiter avec des exceptions sont :
- dépassement d’indices dans les tableaux
- dépassement de capacité (le résultat d’un calcul est plus grand que le maximum représentable par la variable : ex stocker un nombre plus grand que 255 dans un char)
- division par zéro
- allocation mémoire impossible (manque de mémoire).
-
Le mécanisme des exceptions se gère avec 3 mots clés
- try : signale une portion de code pouvant générer un erreur
- throw : lance une erreur
- catch : traite l’erreur
int division(int a,int b) // Calcule a divisé par b.
{
if(b==0){
throw string("ERREUR : Division par zéro !"); //lance l’exception
}
else return a/b;
} //sinon calcule la division
int main() {
int a=10,b=0;
try {
cout << a << " / "<< b << " = " << division(a,b) << endl;
}
catch(string const& chaine){
cerr << chaine << endl; //on utilise le flux standard d’erreur
}
return 0;
}-
Chaque bloc try doit être suivi d'un bloc catch
-
Chaque bloc catch doit être précédé d’un bloc try ou d’un bloc catch
-
Le code écrit derrière l’instruction throw n’est pas exécuté. Le code reprend après le bloc catch
-
L’instruction throw doit toujours se trouver dans un bloc try
-
On attrape les exceptions par référence constante (const&) et pas par valeur. Cela permet d'éviter une copie et de conserver le polymorphisme de l'objet reçu
-
On peut lancer n’importe quel objet comme exception (entier, chaîne de caractère, …)
-
Il faut préciser dans le paramètre du catch quel type on attrape
catch(int e) { …} // On rattrape les entiers lancés
catch(string const& e){} // On rattrape les strings lancés.
catch(Animal const& e) {} // On rattrape les animaux. - Pour attraper n’importe quel type d’exception on utilise …
catch(…){//on ne peut pas utilise l’objet puisque non passé en paramètre }- On peut aussi attraper toutes les exceptions qui dérivent de la classe standard exception
catch(exception const& e){
cerr << e.what;
} //on peut utiliser e- Il est possible de créer ses propres classes d’exception en dérivant la classe exception. Cela permet de préciser plusieurs éléments sur l’exception
# include <exception>
struct DivisionParZeroException : public std::exception
{
DivisionParZeroException (const std::string & message = "a essaye de diviser par zero "):m_message ( message ) {}
virtual ~ DivisionParZeroException () throw () {}
virtual const char * what () const throw () {
return m_message . c_str ();
}
private :
std :: string m_message ;
};
double quotient ( const int numerateur , const int denominateur )
{
if(denominateur ==0)
throw DivisionParZeroException();
// ...
}
// dans la fonction appelante ( main par exemple ) :
try
{
double div = quotient (3, 0);
}
catch (DivisionParZeroException & e)
{
cout << " Erreur : " << e. what() << endl;
}