This shows you the differences between two versions of the page.
Both sides previous revision Previous revision Next revision | Previous revision | ||
in202:seance_1:td_1 [2021/03/22 07:32] bmonsuez [Etape 2 : Compilation d'un exemple simple de classe C++] |
in202:seance_1:td_1 [2022/11/18 10:46] (current) |
||
---|---|---|---|
Line 5: | Line 5: | ||
==== Etape 1 : Installation de l'environnement ==== | ==== Etape 1 : Installation de l'environnement ==== | ||
- | En vous référant à la documentation disponible sous ce lien et en n'hésitant pas à demander à l'enseignant de vous accompagner, installer un environnement de développement sur votre ordinateur. | + | En vous référant à la [[..:outils|documentation disponible]] sous ce lien et en n'hésitant pas à demander à l'enseignant de vous accompagner, installer un environnement de développement sur votre ordinateur. |
==== Etape 2 : Compilation d'un exemple simple de classe C++ === | ==== Etape 2 : Compilation d'un exemple simple de classe C++ === | ||
Line 114: | Line 114: | ||
std::cout << "4 * B = " << (4 * valueB) << std::endl; | std::cout << "4 * B = " << (4 * valueB) << std::endl; | ||
+ | return 0; | ||
} | } | ||
</code> | </code> | ||
Line 119: | Line 120: | ||
Assurez vous que le projet compile et s'exécute correctement. | Assurez vous que le projet compile et s'exécute correctement. | ||
+ | <hidden Correction> | ||
+ | Il suffit de vérifier que le programme compile et s'exécute correctement. | ||
+ | </hidden> | ||
===== Seconde partie : Création d'une classe "Compteur" en C++ ===== | ===== Seconde partie : Création d'une classe "Compteur" en C++ ===== | ||
Line 125: | Line 129: | ||
Créer un projet "console" vide dans votre environnement de développement. | Créer un projet "console" vide dans votre environnement de développement. | ||
+ | |||
+ | <hidden Correction> | ||
+ | Cela dépend de votre environnement. | ||
+ | </hidden> | ||
==== Question 2.2 ==== | ==== Question 2.2 ==== | ||
Line 138: | Line 146: | ||
}; | }; | ||
</code> | </code> | ||
+ | |||
+ | <hidden Correction> | ||
+ | A nouveau, il suffit de créer les deux fichiers. Par contre, il est important de s'assure que le contenu d'un fichier entête (ie. .h, .hh ou .hpp) ne puissent pas être compilé deux fois même s'il est chargé plus d'une fois. Pour ce faire, il est de bonne pratique d'utiliser la structure suivante : | ||
+ | <code cpp> | ||
+ | #ifndef nameHPP | ||
+ | #define nameHPP | ||
+ | |||
+ | // contenu de votre fichier. | ||
+ | #endif | ||
+ | </code> | ||
+ | |||
+ | où ''name'' correspond au nom de votre fichier, "HPP" pour l'extension '.hpp', "H" pour l'extension '.h', ainsi de suite. | ||
+ | |||
+ | La première fois que le fichier est chargé par le compilateur, l'identifiant ''nameHPP'' n'est pas défini, on analyse le code situé après la directive ''#ifndef''. La première ligne suivante : ''#define nameHPP'' définit l'identifiant ''nameHPP'' et puis ensuite le contenu du fichier est analysé. | ||
+ | |||
+ | Si on charge une seconde fois le fichier, l'identifiant ''nameHPP'' est défini, donc le contenu situé entre la directive ''#ifndef nameHPP'' et la directive ''#endif'' est ignoré. Cela empêche d'avoir des erreurs liées au fait que l'on charge le fichier d'entête plus d'une fois. | ||
+ | |||
+ | </hidden> | ||
=== Question 2.3 === | === Question 2.3 === | ||
Line 163: | Line 189: | ||
Expliquer ce que font ces fonctions membres. | Expliquer ce que font ces fonctions membres. | ||
+ | |||
+ | <hidden Correction> | ||
+ | La première fonction augmente le compteur de un en un tant que la valeur maximale n'est pas atteinte. Si la valeur maximale est atteinte, il recommance à compter à partir de la valeur 0. | ||
+ | |||
+ | La seconde fonction remet le compteur à 0. | ||
+ | </hidden> | ||
=== Question 2.4 === | === Question 2.4 === | ||
Line 199: | Line 231: | ||
Expliquer le comportement des compteurs. | Expliquer le comportement des compteurs. | ||
+ | <hidden Correction> | ||
+ | Le ''counterA'' a été créé avec ''count'' à 0 et ''max'' à 2. | ||
+ | |||
+ | Le ''counterB'' a été créé avec ''count'' à 0 et ''max'' à 4. | ||
+ | |||
+ | Incrémenter le compteur ''counterA'' va générer la séquence : 0, 1, 2, 0, ... | ||
+ | |||
+ | Incrémenter le compteur ''counterB'' va générer la séquence : 0, 1, 2, 3, ... | ||
+ | |||
+ | </hidden> | ||
===== Troisième partie : Les constructeurs ===== | ===== Troisième partie : Les constructeurs ===== | ||
Line 227: | Line 269: | ||
} | } | ||
</code> | </code> | ||
+ | |||
+ | <hidden Correction> | ||
+ | Vous constatez que les valeurs des champs ''count'' et ''max'' ont des valeurs qui sortent de nul part. | ||
+ | </hidden> | ||
==== Question 3.2 ==== | ==== Question 3.2 ==== | ||
Line 239: | Line 285: | ||
Ajouter ces constructeurs à votre classe. | Ajouter ces constructeurs à votre classe. | ||
+ | |||
+ | <hidden Correction> | ||
+ | |||
+ | Nous ajoutons les deux constructeurs comme suit: | ||
+ | <code cpp> | ||
+ | class MyCounter | ||
+ | { | ||
+ | public: | ||
+ | int counter; | ||
+ | int max; | ||
+ | | ||
+ | explicit MyCounter(int theMaxValue): count(0), max(theMaxValue) {} | ||
+ | MyCounter(int theCounter, int theMaxValue): count(theCounter), max(theMaxValue) {} | ||
+ | | ||
+ | void increment() { | ||
+ | counter ++; | ||
+ | if(counter > max) | ||
+ | counter = 0; | ||
+ | } | ||
+ | |||
+ | void reset() { | ||
+ | counter = 0; | ||
+ | } | ||
+ | }; | ||
+ | </code> | ||
+ | |||
+ | Comme nous ne souhaitons pas une conversion automatique d'un entier en compteur, nous devons mettre ''explicit'' pour empêcher que le compilateur utiliser le constructeur ''MyCounter(int)'' comme constructeur de conversion lui permettant de convertir un entier en un objet de type ''MyCounter''. | ||
+ | |||
+ | </hidden> | ||
=== Question 3.2.2 === | === Question 3.2.2 === | ||
Modifier la fonction ''testCounter'' pour utiliser ces constructeurs afin de créer et d'initialiser les objets ''counterA'' et ''counterB''. | Modifier la fonction ''testCounter'' pour utiliser ces constructeurs afin de créer et d'initialiser les objets ''counterA'' et ''counterB''. | ||
+ | |||
+ | <hidden Correction> | ||
+ | |||
+ | Le code est simplifier, puisqu'il suffit de passer au constructeur la valeur maximale du compteur, supprimant les initialisations des champs ''counter'' et ''max'' qui ne sont désormais plus nécessaires et souhaitables. | ||
+ | |||
+ | <code cpp> | ||
+ | void testCounter() | ||
+ | { | ||
+ | MyCounter counterA(2); | ||
+ | MyCounter counterB(4); | ||
+ | | ||
+ | for(int i = 0; i < 4; i++) | ||
+ | { | ||
+ | std::cout << "compteur A: (" << counterA.counter << ", " << counterA.max << ")" << std::endl; | ||
+ | std::cout << "compteur B: (" << counterB.counter << ", " << counterB.max << ")" << std::endl; | ||
+ | counterA.increment(); | ||
+ | counterB.increment(); | ||
+ | } | ||
+ | } | ||
+ | </hidden> | ||
===== Quatrième partie : Rendre publique/privée des champs et fonctions ===== | ===== Quatrième partie : Rendre publique/privée des champs et fonctions ===== | ||
Line 282: | Line 377: | ||
Modifier votre classe en rendant les champs ''max'' et ''counter'' privés et en déclarant des méthodes d'accès ''getCounter'' et ''getMax''. | Modifier votre classe en rendant les champs ''max'' et ''counter'' privés et en déclarant des méthodes d'accès ''getCounter'' et ''getMax''. | ||
+ | <hidden Correction> | ||
+ | Il suffit de déplacer les deux champs ''counter'' et ''max'' dans la section privée ''private'' de la classe et d'ajouter les méthodes ''int getCounter() const'' et ''int getMax() const'' qui retourne une copie du champ ''counter'' et du champ ''max''. On ajoute le mot clé ''const'' pour indiquer que la méthode ne modifie aucun champ de l'objet et donc ne modifie pas l'objet. | ||
+ | <code cpp> | ||
+ | class MyCounter | ||
+ | { | ||
+ | private: | ||
+ | int counter; | ||
+ | int max; | ||
+ | public: | ||
+ | explicit MyCounter(int theMaxValue): count(0), max(theMaxValue) {} | ||
+ | MyCounter(int theCounter, int theMaxValue): count(theCounter), max(theMaxValue) {} | ||
+ | | ||
+ | int getCounter() const { return counter; } | ||
+ | int getMax() const { return max; } | ||
+ | |||
+ | void increment() { | ||
+ | counter ++; | ||
+ | if(counter > max) | ||
+ | counter = 0; | ||
+ | } | ||
+ | |||
+ | void reset() { | ||
+ | counter = 0; | ||
+ | } | ||
+ | }; | ||
+ | </code> | ||
+ | </hidden> | ||
==== Question 4.2 ==== | ==== Question 4.2 ==== | ||
Vérifier que la compilation de la fonction ''testCounter'' génère des erreurs. | Vérifier que la compilation de la fonction ''testCounter'' génère des erreurs. | ||
+ | |||
+ | <hidden Correction> | ||
+ | Le compilateur indique qu'il n'est pas possible d'accéder aux champs ''counter'' et ''max''. | ||
+ | </hidden> | ||
==== Question 4.3 ==== | ==== Question 4.3 ==== | ||
Line 292: | Line 418: | ||
Modifier la fonction ''testCounter'' pour désormais appeller les méthodes d'accès. Vérifier le bon fonctionnement de la fonction ''testCounter''. | Modifier la fonction ''testCounter'' pour désormais appeller les méthodes d'accès. Vérifier le bon fonctionnement de la fonction ''testCounter''. | ||
+ | <hidden Correction> | ||
+ | |||
+ | Il suffit de remplacer les accès aux champs ''max'' et ''counter'' par des appels aux méthodes ''getMax()'' et ''getCounter()''. | ||
+ | |||
+ | <code cpp> | ||
+ | void testCounter() | ||
+ | { | ||
+ | MyCounter counterA(2); | ||
+ | MyCounter counterB(4); | ||
+ | | ||
+ | for(int i = 0; i < 4; i++) | ||
+ | { | ||
+ | std::cout << "compteur A: (" << counterA.getCounter() << ", " << counterA.getMax() << ")" << std::endl; | ||
+ | std::cout << "compteur B: (" << counterB.getCounter() << ", " << counterB.getMax() << ")" << std::endl; | ||
+ | counterA.increment(); | ||
+ | counterB.increment(); | ||
+ | } | ||
+ | } | ||
+ | </hidden> | ||