User Tools

Site Tools


in204:tds:sujets:td7:part2

Differences

This shows you the differences between two versions of the page.

Link to this comparison view

Next revision
Previous revision
in204:tds:sujets:td7:part2 [2019/11/03 10:28]
bmonsuez created
in204:tds:sujets:td7:part2 [2022/11/18 10:48] (current)
Line 1: Line 1:
-====== Partie II – Destructeurs ​======+====== Partie II – Vérifier que les exceptions sont bien capturées.======
  
-Nous créons les classes suivantes ​:+[[in204:tds:​sujets:​td7|TD7]]
  
-<code cpp> 
-class GraphicalObject ​ 
-{ 
-    public: ​       
-       ​virtual void draw () const = 0 ;  
-       ​~GraphicalObject() { std::cout << "& Delete GraphicalObject \n"; } 
-        
-}; 
  
-class Linepublic GraphicalObject  +L'​objet des questions suivantes est de pouvoir vérifier au moment de la compilation que les exceptions sont bien capturées ou bien que seules les exceptions indiquées sont supposées être déclencheés (cf. [[in204:cpp:syntax:exceptions:contract|les annotations relatives aux exceptions]]).
-+
-    public: +
-       ​virtual void draw () const { std::cout << "​Line";​ } ;  +
-       ​~Line({ std::cout << "​Delete Line\n";​ } +
-        +
-};+
  
-class Circle: public GraphicalObject ​ +===== Question n°1 =====  
-{ + 
-    ​public:​ +L’exception ''​division_by_zero''​ peut être levée par la fonction ''​divide''​. Ajouter cette information à la fonction ''​divide''​.  
-       virtual void draw() const { std::​cout ​<< " Circle";​ } ;  + 
-       ~Circle ​ ​() ​{ std::cout <"​Delete Circle ​ \n"} +<hidden Correction>​ 
-       + 
-};+ 
 +Nous considérons que l'​exception ''​division_by_zero''​ n'est plus capturée par la fonction ''​divide''​ et est propagée aux fonctions appelantes. 
 + 
 +Dans ce cas nous devons indiquer que la fonction ''​divide''​ peut générer une exception. Nous avons plusieurs possibilités pour le faire. 
 + 
 +  ​* Indiquer que la fonction ''​divide''​ genére une exception de type ''​division_by_zero''​.\\ <code cpp> 
 +double divide(double, doublethrow(division_by_zero);​ 
 +</code> 
 + 
 +  * Indiquer que la fonction ''​divide''​ genére une exception sans spécifier laquelle. Dans ce cas, les syntaxes suivantes sont équivalentes\\ <code cpp> 
 +double divide(double,​ double) noexcept(false)
 +double divide(double,​ double) throw(...);
 </​code>​ </​code>​
  
  
-Nous créons le tableau d’objet suivant ​:+Ceci nous donne en conséquence les codes suivants pour la méthode ''​divide'' ​:
  
 <code cpp> <code cpp>
-std::​vector<​GraphicalObject*>​ createGraphicalObjects( +double divide(double theNumerator,​ double theDivisor) throw(division_by_zero)
-    int theSize)+
 { {
-    ​std::​vector<​GraphicalObject*>​ graphicalObjects(theSize); +    ​if(theDivisor == 0) 
-    for(int i=0; i < size; i+++        throw division_by_zero(); 
-    { +    return ​theNumerator / theDivisor;
-       ​graphicalObjects[i] = new Line(); +
-       ​graphicalObjects[i++] = new Circle(); +
-    } +
-    return ​graphicalObjects;+
 } }
 +</​code>​
  
-Nous définissons une fonction de dession pour l'​ensemble des éléments ​ + 
-dans le tableau.+Jusqu'​à la version C++14, nombreux étaient les compilateur qui considérait que :
 <code cpp> <code cpp>
 +double divide(double,​ double) throw(division_by_zero);​
 +</​code>​
 +était equivalent à :
 +<code cpp>
 +double divide(double,​ double) noexcept(false);​
 +</​code>​
 +En fait les compilateur ne vérifiaient pas la nature des exceptions qui étaient capturées. De ce fait, depuis C++17, cette fonctionnalité a été déclarée comme "​abandonnées"​ et désormais il est demandé de déclarer une fonction qui ne lève pas d'​exception par : ''​noexcept''​ ou par ''​noexcept(true)''​ et une foncion qui lève une exception par soit ''​noexcept(false)''​ ou ''​throw(...'​)''​.
  
-void drawGraphicalObjects(std::vector<GraphicalObject*>& theGraphicalObjects) +</​hidden>​ 
-+ 
-    for(auto it theGraphicalObjects.begin(); ​ + 
-        ​it ​theGraphicalObjects.end(); it++) +===== Question n°2 =====  
-    { + 
-       ​delete it->draw(); +Exécutez votre programme. 
-    } + 
-}+<hidden Correction>​ 
 + 
 + 
 +Comme l'​exception n'est jamais capturée, celle-ci appelle le handler par défaut ​std::terminate qui termine le programme. 
 + 
 +</hidden
 +===== Question n°3 =====  
 + 
 +Ajoutez les informations complémentaires à votre programme pour éviter ce comportement
 + 
 +<hidden Correction>​ 
 + 
 + 
 +Pour la méthode ''​test_divide'',​ nous devons  
 + 
 +  - indiquer qu'​elle ne génère pas d'​exceptionsEn conséquence,​ nous devons lui ajouter un des marquages suivants : 
 +<code cpp>  
 +void test_divide() noexcept
 +void test_divide() noexcept(true); 
 +void test_divide() throw(); // Attention, n'est plus supporté depuis la version C++17.
 </​code>​ </​code>​
  
 +Si nous exécutons le code, l'​exception n'est pas générée. Et le code s'​exécute comme si cette exception n'​avait pas existée.
  
 +</​hidden>​
  
-Nous créons la fonction de destruction du tableau suivante: +===== Question n°4 ===== 
-<code cpp>+
  
-void deleteGraphicalObjects(std::vector<GraphicalObject*>& theGraphicalObjects)+Complétez les informations pour que la fonction ''​test_divide''​ capture effectivement l'​exception. 
 + 
 +<​hidden>​ 
 + 
 + 
 +Ce qui donne pour cette fonction le code suivant ​: 
 + 
 +<code cpp> 
 +void test_divide(noexcept
 { {
-    ​for(auto it = theGraphicalObjects.begin();  +  double i, j; 
-        ​it ​theGraphicalObjects.end(); it++)+  ​for(;;) { 
 +    ​std::​cout ​<< "Le numerateur ​(0 pour arreter): "; 
 +    std::cin >> i; 
 +    if(i == 0) 
 +      break; 
 +    std::cout << " Le denominateur : "; 
 +    std::cin >> j; 
 +    try
     {     {
-       ​delete *it;+        std::cout << "​Resultat:​ " << divide(i,j) << std::endl;
     }     }
 +    catch(division_by_zero anException)
 +    {
 +        std::cout << "​Erreur:​ " << anException.what() << std::endl;
 +    }
 +  } 
 } }
 </​code>​ </​code>​
  
-Et nous testons avec le code suivant :+Nous pouvons désormais marquer la fonction ''​main''​ comme étant une fonction ne génèrant aucune exception. ​
  
 <code cpp> <code cpp>
- +void main() noexcept 
-auto graphicalObjects = createGraphicalObjects(10); +
-deleteGraphicalObjects(graphicalObjects);​ +/// 
 +}
 </​code>​ </​code>​
  
-===== Question n°1 ===== +et nous obtiendrons une compilation garantissant ​que toutes les exceptions sont bien capturées.
- +
-Justifier la sortie produite à l’écran ? Est-ce ​que c’est le comportement désiré ? +
- +
-===== Question n°2 =====+
  
-Proposer une modification pour obtenir le comportement souhaité. ​ 
  
-Tester après cette modification.+</​hidden>​
  
in204/tds/sujets/td7/part2.1572776902.txt.gz · Last modified: 2019/11/03 10:28 by bmonsuez