====== Partie I – Manipulation des Exceptions====== [[in204:tds:sujets:td7|TD7]] ===== Question n°1 : Gestion simple des exceptions en C++ ===== ==== Question n°1.1 ==== Implanter le code suivant dans un nouveau projet. #include double divide(double a, double b); void test_divide(); void test_divide() { double i, j; for(;;) { std::cout << "Le numerateur (0 pour arreter): "; std::cin >> i; if(i == 0) break; std::cout << " Le denominateur : "; std::cin >> j; std::cout << "Resultat: " << divide(i,j) << std::endl; } } double divide(double a, double b) { try { if(!b) throw b; } catch (double b) { std::cout << "Ne peut pas diviser par zero.\n"; return b; } return a/b; } void main() { test_divide() ; } ==== Question n°1.2 ==== Procéder à une exécution et regarder ce qui se passe quand une division par 0 se produit. Lors d'une division par zéro se produit, le code std::cout << "Ne peut pas diviser par zero.\n"; return b; est exécuté et la fonction retourne ''0''. Ceci signifie que l'exception de type ''double'' ayant pour valeur ''0'' a été générée et a été capturée par la clause ''catch(double)''. try { if(!b) throw b; } catch (double b) { std::cout << "Ne peut pas diviser par zero.\n"; return b; } Dans les autres cas, c'est bien le résultat de la division qui est retournée par la fonction. ==== Question n°1.3 ==== Exécuter en mode débogage et placer un point d’arrêt sur le code de capture de l’exception. L'objectif de cette question est de vous faire manipuler vos outils pour utiliser l'environnement de dévogage de votre environnement de développement. Bien entendu, en fonction de votre environnement, vous avez des procédures différentes pour positionner un point d'arrêt. Pour mémoire, voici quelques références pour placer des points d'arrêts sur les différents outils (sans garantie aucune d'exhaustivité). * [[https://code.visualstudio.com/docs/cpp/cpp-debug|Debug C++ in Visual Studio Code]] * [[http://wiki.codeblocks.org/index.php/Debugging_with_Code::Blocks|Debugging with Code::Blocks]] * [[https://docs.microsoft.com/fr-fr/visualstudio/debugger/quickstart-debug-with-cplusplus?view=vs-2019|Quickstart: Debug with C++ using the Visual Studio debugger]] * [[https://medium.com/yay-its-erica/xcode-debugging-with-breakpoints-for-beginners-5b0d0a39d711|Xcode Debugging with Breakpoints (for Beginners)]] * [[https://www.cs.swarthmore.edu/~newhall/unixhelp/howto_gdb.php|gdb (and ddd) Guide]] * [[https://www.emacswiki.org/emacs/DebuggingWithEmacs|Debugging with Emacs]] ===== Question n°2 : Création d’une classe d’exception ===== Nous envisageons désormais faire les choses correctement. Nous souhaitons définir une classe exception qui dérive de la classe [[https://en.cppreference.com/w/cpp/error/exception|std::exception]] se trouvant définie dans le fichier d'entête [[https://en.cppreference.com/w/cpp/header/exception|]]. Plus spécifiquement, nous souhaitons la faire dériver de la classe [[https://en.cppreference.com/w/cpp/error/runtime_error|std::runtime_error]] qui elle-même dérive de [[https://en.cppreference.com/w/cpp/error/exception|std::exception]]. Cette classe devra s’appeler ''division_by_zero''. ==== Question n°2.1 ==== Créer la classe ''division_by_zero''. Elle pourra être définie dans un fichier d’entête ''math.hpp'' qui contiendra aussi l’entête de la fonction ''divide''. Le fichier associé ''math.cpp'' contiendre la code de la fonction divide. Penser à fournir un message d’erreur cohérent. Nous nous proposons de créer un fichier ''math.hpp'' qui a le contenu suivant : #ifndef mathHPP #define mathHPP #include #include class division_by_zero: public std::runtime_error { public: division_by_zero(): std::runtime_error("Division by zero") {} }; double divide(double a, double b); #endif Ainsi que le fichier ''math.cpp'' qui contient le code de la fonction ''divide''. #include "math.hpp" double divide(double a, double b) { try { if(!b) throw b; } catch (double b) { std::cout << "Ne peut pas diviser par zero.\n"; return b; } return a/b; } ==== Question n°2.2 ==== Modifier les fonctions ''divide'' et ''test_divide'' pour prendre ne plus lancer et capturer une exception de type ''double'' mais de type ''division_by_zero''. La fonction modifiée s'écrit dorénavant comme suit : inline double divide(double a, double b) { try { if(b == 0) throw division_by_zero(); } catch (division_by_zero) { std::cout << "Ne peut pas diviser par zero.\n"; return 0; } return a/b; }