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> | ||