This shows you the differences between two versions of the page.
| Next revision | Previous revision | ||
|
in204:tds:sujets:td8:part2 [2019/11/11 15:45] bmonsuez created |
in204:tds:sujets:td8:part2 [2022/11/18 10:49] (current) |
||
|---|---|---|---|
| Line 1: | Line 1: | ||
| - | ====== Section critique ====== | + | ====== Partie II – Destructeurs ====== |
| - | [[in204:tds:sujets:td8|TD8]] | + | Nous créons les classes suivantes : |
| - | ===== Références===== | + | <code cpp> |
| + | class GraphicalObject | ||
| + | { | ||
| + | public: | ||
| + | virtual void draw () const = 0 ; | ||
| + | ~GraphicalObject() { std::cout << "& Delete GraphicalObject \n"; } | ||
| + | |||
| + | }; | ||
| - | [[http://en.cppreference.com/w/cpp/thread/unique_lock|std::unique_lock]] | + | class Line: public GraphicalObject |
| - | [[http://en.cppreference.com/w/cpp/thread/mutex|std::mutex]] | + | { |
| + | public: | ||
| + | virtual void draw () const { std::cout << "Line"; } ; | ||
| + | ~Line() { std::cout << "Delete Line\n"; } | ||
| + | |||
| + | }; | ||
| - | ===== Question n°1===== | + | class Circle: public GraphicalObject |
| + | { | ||
| + | public: | ||
| + | virtual void draw() const { std::cout << " Circle"; } ; | ||
| + | ~Circle () { std::cout << "Delete Circle \n"; } | ||
| + | |||
| + | }; | ||
| + | </code> | ||
| - | Nous supposons que nous avons deux fonctions, une première fonction calcule la valeur maximale d’un tableau numérique : | + | |
| + | Nous créons le tableau d’objet suivant : | ||
| <code cpp> | <code cpp> | ||
| - | void array_find_max(const std::vector<int>& theArray, int* theMaxValue) | + | std::vector<GraphicalObject*> createGraphicalObjects( |
| - | !{ | + | int theSize) |
| - | int result = theArray[0]; | + | { |
| - | for (int i = 1; i < (int)theArray.size(); i++) | + | std::vector<GraphicalObject*> graphicalObjects(theSize); |
| - | { | + | for(int i=0; i < size; i++) |
| - | if (theArray[i] > result) | + | { |
| - | result = theArray[i]; | + | graphicalObjects[i] = new Line(); |
| - | } | + | graphicalObjects[++i] = new Circle(); |
| - | *theMaxValue = result; | + | } |
| + | return graphicalObjects; | ||
| } | } | ||
| </code> | </code> | ||
| - | la seconde fonction modifie le tableau en multipliant chaque valeur numérique du tableau par 2 : | + | Nous définissons une fonction de dessin pour l'ensemble des éléments |
| + | dans le tableau. | ||
| <code cpp> | <code cpp> | ||
| - | void array_multiply_by(std::vector<int>& theArray, int theValue) | + | |
| + | void drawGraphicalObjects(std::vector<GraphicalObject*>& theGraphicalObjects) | ||
| { | { | ||
| - | for (int i = 1; i < theArray.size(); i++) | + | for(auto it = theGraphicalObjects.begin(); |
| - | theArray[i] *= theValue; | + | it < theGraphicalObjects.end(); it++) |
| + | { | ||
| + | (*it)->draw(); | ||
| + | } | ||
| } | } | ||
| </code> | </code> | ||
| - | Ecrire chacune des fonctions. | ||
| - | ===== Question 2 ===== | ||
| - | |||
| - | Nous souhaitons exécuter en parallèle les deux fonctions. | ||
| - | |||
| - | Exécuter plusieurs fois ces fonctions sur un tableau de grande taille que vous créez soit de manière aléatoire soit de manière cycliques. Ci-dessous quelques exemples de fonctions générant des tableaux de taille ''n'' et ayant comme valeur des nombres entre ''0'' et ''theMaxValue''. | ||
| + | Nous créons la fonction de destruction du tableau suivante: | ||
| <code cpp> | <code cpp> | ||
| - | void initialize_array(std::vector<int>& theArray, int theSize, | + | |
| - | int theMaxValue) | + | void deleteGraphicalObjects(std::vector<GraphicalObject*>& theGraphicalObjects) |
| { | { | ||
| - | theArray.clear(); | + | for(auto it = theGraphicalObjects.begin(); |
| - | int step = theMaxValue / 3; | + | it < theGraphicalObjects.end(); it++) |
| - | theArray[0] = 0; | + | { |
| - | for (int i = 1; i < theSize; i++) | + | delete *it; |
| - | theArray[i] = (theArray[i-1] + step) % (theMaxValue + 1); | + | } |
| } | } | ||
| </code> | </code> | ||
| - | Ou | + | |
| + | Et nous testons avec le code suivant : | ||
| <code cpp> | <code cpp> | ||
| - | void initialize_random_array(std::vector<int>& theArray, int theSize, | + | |
| - | int theMaxValue) | + | auto graphicalObjects = createGraphicalObjects(10); |
| - | { | + | drawGraphicalObjects(graphicalObjects); |
| - | theArray.clear(); | + | deleteGraphicalObjects(graphicalObjects); |
| - | for (int i = 0; i < theSize; i++) | + | |
| - | theArray[i] = std::rand() % (theMaxValue + 1); | + | |
| - | } | + | |
| </code> | </code> | ||
| - | Expliquer pourquoi les résultats ne sont pas toujours cohérents ? ie. que la valeur maximale retournée est supérieure à la valeur maximale du tableau spécifiée au montant de sa création. | + | ===== Question n°1 ===== |
| - | ===== Question n°3 ===== | + | Justifier la sortie produite à l’écran ? Est-ce que c’est le comportement désiré ? |
| - | Il faut utiliser un verrou qui permet à une méthode de se garantir l’exclusivité de l’usage du tableau. Pour ce faire, nous pouvons utiliser un objet std::mutex qui encapsule un mécanisme d’exclusion mutuelle. | + | <hidden Correction> |
| - | L’objet [[http://en.cppreference.com/w/cpp/thread/unique_lock|std::unique_lock]] permet d’obtenir un accès exclusif sur un object [[http://en.cppreference.com/w/cpp/thread/mutex|std::mutex]]. Quand nous écrivons le code suivant : | + | |
| - | <code cpp> | + | Le destructeur appellé est celui de l'objet de base. Nous souhaitons appeller le destructeur de l'objet véritablement détruit et non celui de l'objet de base. |
| - | #include <iostream> // std::cout | + | |
| - | #include <thread> // std::thread | + | |
| - | #include <mutex> // std::mutex, std::unique_lock | + | |
| - | std::mutex mtx; // mutex fournissant le mécanisme d’exclusion mutuelle. | + | </hidden> |
| - | void my_function (int n, char c) { | + | ===== Question n°2 ===== |
| - | // section critique, tant que l'objet lck existe, personne ne pourra | + | |
| - | // accéder à mtx. | + | |
| - | std::unique_lock<std::mutex> lck(mtx); | + | |
| - | // Code s'exécutant. | + | |
| - | } | + | |
| - | </code> | + | |
| - | ==== Question n°3.1 ==== | + | Proposer une modification pour obtenir le comportement souhaité. |
| - | Modifier les fonctions | + | |
| - | <code cpp> | + | Tester après cette modification. |
| - | int array_find_max(std::vector<int>& theArray, int* theMaxValue) | + | |
| - | </code> | + | <hidden Correction> |
| + | |||
| + | Nous déclarons le destructeur dans la classe de base comme étant virtuel. | ||
| - | et | ||
| <code cpp> | <code cpp> | ||
| - | void array_multiply_by(std::vector<int>& theArray, int theValue) | + | class GraphicalObject |
| - | </code> | + | { |
| - | pour implanter le mécanisme d’exclusion mutuelle propose. | + | public: |
| + | virtual void draw () const = 0 ; | ||
| + | ~GraphicalObject() { std::cout << "& Delete GraphicalObject \n"; } | ||
| + | | ||
| + | }; | ||
| - | ==== Question n°3.2 ==== | + | class Line: public GraphicalObject |
| - | Exécuter le code et vérifier que les résultats sont dorénavant cohérents. | + | { |
| + | public: | ||
| + | virtual void draw () const { std::cout << "Line"; } ; | ||
| + | ~Line() { std::cout << "Delete Line\n"; } | ||
| + | |||
| + | }; | ||
| + | class Circle: public GraphicalObject | ||
| + | { | ||
| + | public: | ||
| + | virtual void draw() const { std::cout << " Circle"; } ; | ||
| + | ~Circle () { std::cout << "Delete Circle \n"; } | ||
| + | | ||
| + | }; | ||
| + | </code> | ||
| + | Désormais, c'est bien le destructeur de l'objet qui est détruit qui est appellé et pas uniquement le destructeur de la classe de base. | ||
| + | </hidden> | ||