User Tools

Site Tools


in204:tds:sujets:td7:part3

Differences

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

Link to this comparison view

Both sides previous revision Previous revision
Next revision
Previous revision
in204:tds:sujets:td7:part3 [2020/10/20 10:45]
bmonsuez [Question n° 1]
in204:tds:sujets:td7:part3 [2022/11/18 10:48] (current)
Line 1: Line 1:
-====== Partie III – Algorithmes génériques======+====== Partie III –  ​Augmenter l’expressivité des exceptions======
  
-Dans la conclusion du cours, nous affirmons qu’un intérêt du polymorphisme,​ c’est de pouvoir écrire un algorithme « générique », c’est à dire un algorithme qui pourra fonctionner pour des objets représentant des données de plusieurs types.+[[in204:​tds:​sujets:​td7|TD8]]
  
-Nous considérons un algorithme ​de tri très simple ​qui fonctionne sur des entiers ​:+Nous souhaitons créer une nouvelle classe d’exception qui dérive ​de la classe exception et qui compte le nombre de fois qu’une exception est capturée. 
 +Nous proposons que cette exception extended_exception dérive de la classe de base std::​exception et fournisse en complément ​des méthodes offertes par la classe de base les méthodes suivantes ​:
  
 <code cpp> <code cpp>
-void insertion_sort(std::vector<​int>&​ anArray)+#​include<​exception>​ 
 +... 
 + 
 +class extended_exception : public ​std::runtime_error
 { {
- for (int i = 0; i < anArray.size(); i++) +  public: 
- { +    void catched(); 
- for (int j = i + 1; j < anArray.size(); j++) +      // Est appelé chaque fois que l’on souhaite indiqué à la classe qu’elle a été 
- +      // capturée.  
- if (anArray[i] > anArray[j]) +   int getCatchNumber() const
- std::​swap(anArray[i],​ anArray[j]); +      // Retourne le nombre de fois que l’exception a été capturée. 
- +};
- } +
-}+
 </​code>​ </​code>​
  
-Cet algorithme fonctionne uniquement pour des entiers. Nous nous proposons de transformer cette fonction afin qu’elle puisse aussi bien trier des entiers mais aussi des réels ou des complexes. +===== Question ​n°1 ===== 
- +
-===== Question ​n° 1===== +
- +
-Pour ce faire, nous concevons une classe « abstraite » ayant comme nom « Base » qui expose les fonctions nécessaires à l’écriture de l’algorithme de tri.  +
- +
-Nous souhaitons utiliser l’algorithme avec la signature suivante : +
- +
-<code cpp> +
-void insertion_sort(std::​vector<​Base*>&​ anArray) +
-</​code>​+
  
-Quelles sont les méthodes virtuelles que la classe ​abstraite doit exposer ? +Proposer une implantation de cette classe
  
 <hidden Correction>​ <hidden Correction>​
  
-La classe doit exposée une méthode permettant de déterminer si un élément est plus grand que l'​autre. Il peut s'agit soit d'une méthode testant si un élément est plus grand que l'​autre : 
  
 +Nous proposons d'​ajouter un compteur qui est incrémenté à chaque fois que l'​exception a été capturée, ie. que la méthode ''​catched''​ a été appellée. Par défaut ce compteur est initialisé à zéro.
 <code cpp> <code cpp>
-class Base+#​include<​exception>​ 
 +... 
 +  
 +class extended_exception:​ public std::​runtime_error
 { {
-public:  +private: 
-    ​virtual bool isGreater(const Base&const = 0;  +    private unsigned m_catched = 0;     
-        // Retourne true si l'objet courant est plus grand. +public: 
-    ...+    ​void catched() { m_catched ++} 
 +      // Est appelé chaque fois que l’on souhaite indiqué à la classe qu’elle a été 
 +      // capturée 
 +   int getCatchNumber() const { return m_catched; } 
 +      // Retourne le nombre de fois que l’exception a été capturée.
 }; };
 </​code>​ </​code>​
  
-Nous pouvons ajouter éventuellement des méthodes complémentaires comme : +Il est nécessaire de définir les constructeurs pour cette classe ​:
 <code cpp> <code cpp>
-    virtual bool isGreaterOrEqual(const Base&) const = 0;  +class extended_exception:​ public std::​runtime_error 
-    ​virtual bool isLess(const ​Base&​) ​const = 0;  +
-    ​virtual bool isLessOrEqual(const Base&const = 0;  +... 
-    ​virtual bool isEqual(const Base&) const = 0;  +public: 
-    ​virtual bool isNotEqual(const ​Base&const = 0;  +    ​explicit extended_exception(const ​std::stringaMessage) 
-</​code>​ +        ​runtime_error(aMessage
- +    ​{} 
-Voire éventuellement une fonction ''​compareTo''​+    ​explicit extended_exception(const ​char* aMessage):  
- +        ​runtime_error(aMessage
-<code cpp> +    {} 
-    virtual int compareTo(const Base&const = 0; +...
-       // retourne -1 si l'​instance courante est plus petite que l'​instance passée en paramètre +
-       // retourne 0 si elles sont égales +
-       // retourne 1 si l'​instance courante est plus grande que l'​instance passée en paramètre.+
 </​code>​ </​code>​
  
 </​hidden>​ </​hidden>​
  
 +===== Question n°2 ===== 
  
-===== Question n° 2=====+Nous proposons de créer une classe exception ''​extended_divide_by_zero''​ qui se comporte comme la classe ''​divide_by_zero''​ mais qui dérive de la classe ''​extended_exception''​.
  
-==== Question n° 2.1====+Réaliser une implantation de la classe extended_divide_by_zero.
  
-Ajouter à la classe de base ''​Base''​ une méthode purement virtuelle ''​print()''​ qui affiche le contenu de la classe sur la console.+<hidden Correction>​
  
-==== Question n° 2.2 ==== 
  
-Créer une fonction ​''​print(std::​vector<​Base*>​ anArray)'' ​qui prend un tableau en paramètre et affiche l’ensemble des éléments contenus dans le tableau sur la console.+La nouvelle classe ​''​extended_divide_by_zero'' ​dérive directement de la classe ''​extended_exception''​Ce qui nous donne le code suivant :
  
-===== Question n° 3 =====+<code cpp> 
 +class extended_divide_by_zero:​ public extended_exception 
 +
 +public:  
 +    division_by_zero():​ extended_exception("​Division by zero"​) 
 +    {} 
 +}; 
 +</​code>​
  
-===== Question n° 3.1 ====+</​hidden>​
  
-Créer une classe Entier qui dérive de la classe « abstraite » ''​Base''​ et qui contient un champ ''​m_value''​ ayant comme type le type ''​int''​.+===== Question n°3 ===== 
  
-==== Question n° 3.2 ====+Nous proposons de modifier la fonction ''​divide''​ pour qu’elle lance non plus une exception ''​divide_by_zero''​ mais ''​extended_divide_by_zero''​.
  
-Créer une fonction ​qui crée un tableau de ''​theNumberOfValues''​ entiers de type Entier+Nous souhaitons tester cette nouvelle ​fonction ​avec le code suivant :
  
 <code cpp> <code cpp>
-std::​vector<​Base*>​ create_integer_array( +double successive_division(double i) nexcept(false)
- size_t theNumberOfValues) +
-</​code>​ +
-qui crée un tableau de ''​theNumberOfValues''​ valeurs commençant par la valeur ''​0''​ et se terminant à la valeur ''​theNumberOfValues-1''​.+
  
-==== Question n° 3.3 ==== +void test_succesive_division() noexcept 
- +
-Créer une fonction qui crée un tableau de ''​theNumberOfValues''​ entiers de type ''​Entier''​ dont les éléments sont des nombres aléatoires compris entre ''​theMinValue''​ et ''​theMaxValue''​.+ double i; 
 + std::cout << "The numerator: "; 
 + std::cin >> i; 
 + try { 
 + successive_division(i);​ 
 +
 + catch (extended_division_by_zero e) { 
 + e.catched(); 
 + std::cout << "​Division by zero occurred after " ​ 
 + << e.getCatchNumber() 
 + << " divisions"​ << std::​endl;​ 
 +
 +}
  
-Cette fonction peut s’implanter comme suit.  +double successive_division(double i)  
-<code cpp>  + noexcept(false)
-std::​vector<​Base*>​ create_random_integer_array( +
- size_t theNumberOfValues,​ int theMinValue,​ int theMaxValue)+
 { {
- std::​random_device rd+  double j
- std::mt19937 gen(rd());  +  std::cout << "Next divisor ​(-1 to stop sequence): "
- std::uniform_int_distribution<​distr(theMinValue,​ theMaxValue); +  std::cin >> j; 
- std::​vector<​Entier*>​ array(theNumberOfValues); +  if (j == -1) 
- for (size_t ​= 0; i < theNumberOfValuesi+++ return i
- array[i] = new Entier(distr(gen)); +  try { 
- return array;+ successive_division(j); 
 + return divide(i,j); 
 +  } 
 +  catch(division_by_zero e
 +  { 
 +   throw extended_division_by_zero(); 
 +  } 
 +  catch (extended_division_by_zero e 
 +  { 
 + e.catched(); 
 + throw e; 
 +  }
 } }
 </​code>​ </​code>​
  
-===== Question n°4 =====+Commentez le résultat de l’exécution.
  
-Modifier ​la fonction de tri ''​insertion_sort(std::​vector<​int>&​ anArray)'' ​afin de ne plus travailler sur des entiers mais sur des objets dérivant ​de la classe « abstraite » ''​Base''​ :+<hidden Correction>​ 
 + 
 +Si nous effectuons un appel à la fonction ​avec la séquence ​de chiffres suivante : 
 +''​20 4 4 1 3 0 3 6 -1''​, nous allons avoir 5 captures ​de l'​exception ​de type ''​extended_divide_by_zero''​. Cependant, nous allons avoir comme message que l'​exception s'est produite après ''​5''​ divisions. Ce qui est conforme. 
 + 
 +Ceci est effectivement logique, puisque quand nous effectuons la capture ​:
  
 <code cpp> <code cpp>
-void insertion_sort(std::​vector<​Base*>&​ anArray)+  try { 
 +    successive_division(j)
 +    return divide(i,​j);​ 
 +  } 
 +  catch(extended_divide_by_zero e) { 
 +    e.catched() ;  
 +    throw e;  
 +  } 
 +  ...
 </​code>​ </​code>​
  
-Tester ​la fonction avec le tableau d’entiers ​que vous avez créé à la question n°3.3.+l'​argument de la clause ''​catch''​ est ''​extended_divide_by_zero'',​ ce qui signifie ​que nous **dupliquons** l'​argument. Nous créons une copie de l'​ancienne exception qui ensuite sera détruite. Ensuite, nous augmentons ​la valeur du champ ''​m_catched''​ qui a été recopiéEn conséquence,​ nous comptons bien le nombre de fois que l'​exception a été capturée à partir du moment où elle a été générée.
  
-===== Question n° 5 ===== +Cependant, nous pouvons éviter ​de recopier l'​exception en effectuant un passage non pas par recopie mais par référence :
-Nous souhaitons étendre le code à une classe ​de réel.+
  
-==== Question n° 5.1 ==== 
- 
-Ecrire une nouvelles classe ''​Reel''​ qui dérive de ''​Base''​ et qui contient un champ  ''​m_value''​ de type ''​double''​. 
- 
-==== Question n° 5.2 ==== 
- 
-Créer une fonction qui crée un tableau de ''​theNumberOfValues''​ objets de type ''​Reel''​ dont les éléments sont des nombres aléatoires compris entre ''​theMinValue''​ et ''​theMaxValue''​. 
- 
-Cette fonction peut s’implanter comme suit.  
-  
 <code cpp> <code cpp>
-std::​vector<​Base*>​ create_random_double_array( +  try 
- size_t theNumberOfValues,​ double theMinValue,​ double theMaxValue) +    ​successive_division(j); 
-+    ​return divide(i,j); 
- std::​random_device rd; +  } 
- std::​mt19937 gen(rd()); +  catch(extended_divide_by_zero&​ e{ 
- std::​uniform_real_distribution<>​ distr(theMinValuetheMaxValue); +    ​e.catched() ;  
- std::​vector<​Base*>​ array(theNumberOfValues);​ +    throw e;  
- for (size_t i = 0; i < theNumberOfValues;​ i+++  } 
- array[i] = new Real(distr(gen)); +  ...
- return array+
-}+
 </​code>​ </​code>​
  
-Vérifier que l’algorithme de tri fonctionne aussi pour cette nouvelle nouvelle classe.+Dans ce cas, l'​exception n'est pas recopiée et supprimée mais modifiée et ensuite propagée. 
 + 
 +</​hidden>​
  
in204/tds/sujets/td7/part3.1603190708.txt.gz · Last modified: 2020/10/20 10:45 by bmonsuez