PROFDINFO.COM

Votre enseignant d'informatique en ligne

Laboratoire 3 - Les relations

Exercice 3.1 - L'oeuf, le moule et le pâtissier: exercice sur la relation d'utilisation

  1. Écrivez la sortie du programme ci-dessous;
  2. déterminez le nombre d'oeufs créés;
  3. et identifiez toutes les relations d'utilisation dans ce programme. Pour chaque relation, identifier la classe dépendante et le type de relation (paramètre, variable locale, valeur de retour).
#include <iostream>
using namespace std;

class COeuf
{
public:
   COeuf() { cout << "Un nouvel oeuf!" << endl; }
   COeuf(const COeuf& Oeuf) { cout << "Un oeuf clone!" << endl; }
   ~COeuf() { cout << "L'oeuf est detruit!" << endl; }
};

class CMoule
{
public:
   CMoule() { cout << "Un nouveau moule" << endl; }
   ~CMoule() { cout << "Le moule est detruit!" << endl; }
   COeuf Creer() { COeuf Oeuf; return Oeuf; }
};

class CPatissier
{
   public:
   CPatissier() { cout << "Un nouveau Patissier" << endl; }
   ~CPatissier() { cout << "Le Patissier est detruit!" << endl; }

   void Manger(COeuf UnOeuf) { cout << "Un Patissier mange un oeuf!" << endl; }
   void Creer() { CMoule Moule; COeuf Oeuf = Moule.Creer(); Manger(Oeuf); }
 };

int main()
{
   CPatissier Roger;
   COeuf Oeuf;
   Roger.Manger(Oeuf);
   Roger.Creer();
}

Exercice 3.2 - L'utilisation

Pour ce exercice, vous devez créer un programme qui permet de pratiquer les tables de multiplications. Voici un exemple de déroulement du programme:

Exemple

 

Pour ce faire, vous devez respecter le diagramme UML suivant:

31uml

 

La classe CPointage permet de conserver le nombre de points de la partie en cours. Elle a un constructeur par défaut qui intialise à zéro les points. La méthode Ajuster vérifie si la réponse de l'étudiant est correcte en utilisant les méthodes des objets Etudiant et Question passés en paramètres. Si c'est le cas, elle affiche "Bravo!" à la console et augmente de 1 le nombre de points. Sinon, elle affiche "Erreur!" à la console. La méthode Afficher affiche les points à la console.

La classe CQuestion conserve les nombres utilisés dans la multiplication. Elle a un constructeur avec paramètres par défaut seulement. La méthode Afficher affiche la question à la console. La méthode SetNombres est un mutateur qui permet de spécifier les deux attributs à la fois. La méthode ÉvaluerRéponse retourne True si la réponse passée en paramètre est égale au produit des deux nombres.

La classe CEtudiant permet de conserver la réponse de l'étudiant. La méthode Répondre commence par demander à la question passée en paramètre de s'afficher à la console, puis attend la réponse de l'usager. La méthode GetReponse est un accesseur.

La classe CEnseignant n'a pas d'attribut. Elle sert seulement à créer des questions. La méthode CreerQuestionchoisit au hasard deux nombres, créé un nouvelle question avec ces deux nombres et retourne la question à l'appelant. Les nombres choisis au hasard ne doivent pas dépasser les valeurs minimales et maximales passées en paramètres.

Il faut obligatoirement utiliser le programme principal suivant:

int main()
{
   srand(static_cast<int>(time(0)));
   
   CEnseignant Joan;
   CEtudiant Paul;
   CPointage Points;

   for(int i=0;i<10;i++)
   {
      CQuestion Question = Joan.CreerQuestion(1,12);
      Paul.Repondre(Question); 
      Points.Ajuster(Question, Paul);
   }

   cout << "Pointage final: ";
   Points.Afficher();
   cout << " sur 10" << endl;
}      

Exercice 3.3- Introduction à la composition

ATTENTION! Pour cet exercice, il vous faut inscrire les réponses aux questions sur une feuille, dans un document électronique ou en commentaire dans le code source.

Un lapin est composé (entre autres) de deux oreilles et d'un nez. À partir des déclarations de classes suivantes:

class COreille
{
public:
   COreille();
   ~COreille();

};

class CNez
{
public:
   CNez();
   ~CNez();
};

const int NbOreilles=2;

class CLapin
{
public:
   CLapin(); 
   ~CLapin();
private:
   COreille Oreilles_[NbOreilles];
   CNez Nez_;
};

et du programme principal suivant:

int main()
{
   CLapin LapinDePaques;
}

 

  1. Déterminez l'ordre de tous les appels des constructeurs et des destructeurs.
    Exemple:
    • appel du constructeur de CNez;
    • appel du destructeur de CNez;
    • appel du constructeur de COreille;
    • appel du constructeur de CLapin;
    • etc.
    Indice: il y a 8 appels de constructeurs et destructeurs.

  2. Si, dans la classe CLapin, on déclare le Nez_ avant les Oreilles_, quel est l'impact sur les appels des constructeurs? des destructeurs?

  3. Remplacez le constructeur par défaut de la classe CNez par un constructeur paramétrique qui prend un int en paramètre (pour spécifier la grosseur du nez), puiz tentez de générer la solution.
    1. Quel erreur survient? Pouvez-vous expliquer cette erreur?

    2. Modifiez le constructeur paramétrique de la classe CNez de façon à ce qu'il devienne un constructeur avec paramètre par défaut qui donne par défaut la valeur zéro (0) à la grosseur du nez. Donnez ici la déclaration de ce constructeur:

    3. Par défaut, un nez se construit avec une grosseur de zéro (0), mais on voudrais bien que lorsque l'on construit un lapin, le nez ait une grosseur de trois (3). Qu'est-ce que vous devez modifier à la définition du constructeur de lapin pour obtenir ce résultat?
  4. Remplacez le constructeur par défaut de la classe COreille par un constructeur paramétrique qui prend un int en paramètre (pour spécifier la grandeur de l'oreille), puiz tentez de générer la solution.
    1. Quel erreur survient? Pouvez-vous expliquer cette erreur?

    2. Modifiez le constructeur paramétrique de la classe COreille de façon à ce qu'il devienne un constructeur avec paramètre par défaut qui donne par défaut la valeur zéro (0) à la grandeur de l'oreille. Donnez ici la déclaration de ce constructeur:

    3. Par défaut, une oreille se construit avec une grandeur de zéro (0), mais on voudrais bien que lorsque l'on construit un lapin, les oreilles aient une grandeur de sept (7). Est-possible? Si oui, comment? Sinon, pourquoi?
  5. Ajoutez le mutateur SetGrosseur(int) à la classe CNez et ajoutez le mutateur SetGrandeur(int) à la classe COreille.
    1. Ajoutez l'accesseur GetNez à la classe CLapin qui retourne une copie du nez du lapin. Notez la déclaration de cet accesseur ici. Écrivez la ligne de code qui permet au programme principal de modifier la grosseur du nez du lapin LapinDePaques.

    2. Ajoutez l'accesseur suivant à la classe CLapin:

      COreille& GetOreille(int index)

      Cet accesseur brise un grand principe de la programmation orientée objets. Pouvez-vous indentifier ce principe, expliquer la raison pour laquelle il est brisé et suggérer une correction?

Exercice 3.4 - L'inventaire

Un magasin détient un inventaire composé d’articles de toutes sortes. Un article est décrit par la classe CArticle et comporte les attributs suivants :

La classe CArticle rend disponible les méthodes publiques suivantes :

Un inventaire est décrit par la classe CInventaire et comporte les attributs suivants :

Voici la déclaration de la classe CInventaire

const int NombreArticlesMax = 100;

class CInventaire
{
public:
   //--- Constructeurs et destructeurs
  CInventaire();

  CInventaire(const CInventaire& Original);
  ~CInventaire();
  
  //--- Accesseurs et mutateurs
  string GetCode(int pos) const;
  string GetNom (string Code) const;
  double GetPrix(string Code) const;
  int    GetQte (string Code) const;
  int    GetNombreArticle() const;
  
  //--- Autres services
  // Ajoute un nouvel article dans le tableau
  // Cette méthode doit faire attention pour ne pas dépasser le nombre maximal d'articles
  void AjouterArticle (string Code, string Nom, double  Prix, int Qte);
  // Augmente ou diminue la quantité d'un article déjà existant
  void AjouterArticle (string Code, int Qte);
  // Calculer le coût total de l'inventaire en multipliant la quantité par le prix de 
  // chaque article, puis en additionnant tous les articles.
  double CalculerCoutInventaire() const;
private:
   // Nombre d'articles de l'inventaire
   int NombreArticles_;
   // Tableau d'articles  
   CArticle Tableau_[NombreArticlesMax];
  }; 

La classe offre les fonctionnalités suivantes:

Le programme client a accès aux méthodes publiques de la classe CInventaire seulement puisque l'accès au tableau d'articles est protégé par l’encapsulation.

Vous devez aussi écrire un programme principal qui teste toutes les fonctionnalités de la classe CInventaire.

 

Exercice 3.5 - Exercice sur la composition

ATTENTION! Pour cet exercice, il vous faut inscrire les réponses aux questions sur une feuille, dans un document électronique ou en commentaire dans le code source.

Déterminez la sortie du programme suivant :

#include <iostream>
using namespace std;

class A
{
public:
	A() { cout << "1"; }
	A(int i) { cout << i ; }
	~A() { cout << "2"; }
};

class B
{
	A a1_;
	A a2_;
public:
	B(int i) : a2_(3) { cout << i; }
	~B() { cout << "4"; }
};

class C
{
	B b_;
	A a_[2];
public:
	C() : b_(5) { cout << "6"; }
	~C() { cout << "7"; }
};

int main()
{
	A a(8);
	B b(9);
	C c;
}

 
      

Sortie:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

Exercice 3.6 - Introduction à l'héritageevolution

L'homme est un primate et un primate est un mammifère.

  1. Quelles sont les trois classes présentes dans ce simple énoncé?

  2. Décrivez les relations d'héritage entre ces classes. Il y en a deux.

  3. Programmez chacune de ces classes avec un constructeur par défaut et un destructeur. Déclarez un objet de la classe CHomme et, à l'aide de sorties à la console, déterminez dans quel ordre les différents constructeurs et destructeurs sont appelés.

  4. Le mammifère possède la méthode publique ErrerDansLesPres qui affiche "la la la" à la console.
    Le primate possède la méthode publique UtiliserOutils qui affiche "Bang bang bang" à la console.
    L'homme possède la méthode publique Discourir qui affiche "Bla bla bla" à la console.
    Identifiez dans le programme principal suivant les lignes que ne compilent pas et expliquez pourquoi ces lignes ne compilent pas. Mettez en commentaire les lignes qui ne compilent pas et indiquez ce que ce programme affiche à la console.

    int main()
    {
       CMammifere Mammi;
       CPrimate Singe;
       CHomme Moi;
    
       Mammi.ErrerDansLesPres();
       Mammi.UtiliserOutils();
       Mammi.Discourir();
       Singe.ErrerDansLesPres();
       Singe.UtiliserOutils();
       Singe.Discourir();
       Moi.ErrerDansLesPres();
       Moi.UtiliserOutils();
       Moi.Discourir();
    }
    

  5. Le mammifère a comme attribut privé son âge (int) et comme attribut protégé le temps de gestation (int).
    Le primate a comme attribut privé son intelligence (int).
    L'homme a comme attribut privé sa langue (string).
    Déterminez pour chaque méthode, les attributs qui sont accessibles:

      Âge Gestation
    QI
    Langue
    ErrerDansLesPres        
    UtiliserOutils        
    Discourir        

    Vérifiez vos réponses à l'aide d'expérimentations.

  6. Ajoutez à la classe CMammifere le constructeur paramétrique qui prend en paramètre l'âge et le temps de gestation et qui initialise les attributs de la classe. Notez la définition de ce constructeur.

  7. Ajoutez à la classe CPrimate le constructeur paramétrique qui prend en paramètre l'âge, le temps de gestation et l'intelligence et qui initialise l'attribut de la classe. Notez la définition de ce constructeur. Le pré-constructeur doit être utilisé de façon à repasser l'âge et le temps de gestation au constructeur paramétrique de la classe CMammifère.

  8. Ajoutez à la classe CHomme le constructeur paramétrique qui prend en paramètre l'âge, le temps de gestation, l'intelligence et la langue et qui initialise l'attribut de la classe. Notez la définition de ce constructeur. Le pré-constructeur doit être utilisé de façon à repasser l'âge, le temps de gestation et l'intelligence au constructeur paramétrique de la classe CPrimate.

  9. Dans le constructeur paramétrique de la classe CMammifere, affichez l'âge et le temps de gestation à la console.
    Dans le constructeur paramétrique de la classe CPrimate, affichez l'intelligence à la console.
    Dans le constructeur paramétrique de la classe CHomme, affichez la langue à la console.
    Vérifiez le bon fonctionnement des constructeurs paramétriques à l'aide du programme principal suivant:

    int main()
     {
        CMammifere Elephant(50, 22);
        CPrimate Singe(90, 6, 90) ;
        CHomme Moi(20, 9, 120, "Francais");
     }

  10. Dessinez le diagramme de classes UML qui représente les trois classes, leurs attributs et leurs mtéhodes ainsi que les relations entre les classes.

Exercice 3.7 - Super Mini Mario 2.0 mario

Pour cet exercice,vous devez programmer le début d'un jeu de Mario en utilisant toute la beauté de la programmation orientée objets. À la fin de cet exercice, le fond sera affiché dans une fenêtre, Super Mini Mario pourra être déplacé dans les quatre directions et le méchant ennemi Koopa se promenera de gauche à droite.

Pour effectuer ce exercice, vous devez utiliser la solution qui vous est fournie ici. Il est gentil votre enseignant n'est-ce pas? La solution, le projet et les fichiers ont été créés pour vous! Il ne reste qu'à remplir les fichiers vides. Le projet utilise la librairie SFML 2.4.1 (Simple and Fast Multimedia Library). Vous trouverez plus d'informations sur cette libraire ici: http://www.sfml-dev.org/documentation/2.4.1-fr/.

Vous devez utiliser Visual Studio 2015 pour cet exercice car cette version de SFML n'est pas compatible avec VS2017 ni VS2013.

La solution doit respecter le diagramme de classes suivant:

uml3.7

La classe CPersonnage est composée (notez la relation de composition ici) uniquement d'un Sprite. Cette classe est déjà faite pour vous (encore une fois merci aux gentils professeurs) et vous n'avez donc pas à la programmer. Par contre, vous aurez besoin d'utiliser certaines de ses méthodes.

La classe CHeros dérive de la classe CPersonnage (notez la relation d'héritage ici):

La classe CEnnemi dérive de la classe CPersonnage et contient une variable booléenne qui indique la direction de déplacement (false: gauche, true: droite).

Vous devez absolument utiliser le programme principal suivant qui est déjà inclus dans la solution de départ:

#include <SFML/Graphics.hpp>
#include "Exercice3.7.h"
#include "Heros.h"
#include "Ennemi.h"
using namespace std;
using namespace sf;

int main()
{
	bool Fin = false;

	RenderWindow Fenetre(VideoMode(Hauteur, Largeur), "SuperMario");
	Texture MarioImg, KoopaImg, FondImg;

	// Charger les textures
	if (!MarioImg.loadFromFile("mario.png"))
	{
		return EXIT_FAILURE;
	}

	if (!KoopaImg.loadFromFile("koopa.png"))
	{
		return EXIT_FAILURE;
	}

	if (!FondImg.loadFromFile("fondmario.bmp"))
	{
		return EXIT_FAILURE;
	}
	Sprite Fond(FondImg); // Créer un sprite avec la texture du fond

						  // Créer Mario et Koopa
	CHeros Mario(MarioImg, 100.0f, 100.0f);
	CEnnemi Koopa(KoopaImg, 200.0f, 200.0f);

	while (!Fin)
	{
		Fenetre.clear();
		Fenetre.draw(Fond);
		Fin = Mario.Bouger();
		Koopa.Deplacer();
		Mario.Afficher(Fenetre);
		Koopa.Afficher(Fenetre);
		Fenetre.display();
		sleep(milliseconds(5));
		Event event; // Événement SFML
		while (Fenetre.pollEvent(event)) 
			// Tant que des événements ont été enregistrés,
			// les traiter
		{
			if (event.type == Event::Closed) // Quelqu'un a cliqué sur le X
			{
				Fenetre.close(); // On ferme la fenêtre
				Fin = true; // Fin du jeu
			}
		}
	}

	return 0;
}

Bon travail!

Exercice 3.8 - Héritage, accès, construction et destruction par P. Prud'homme

Dans le programme suivant: Exercice3.8CodeSource.docx,

  1. Quelles seront les lignes qui ne passeront pas la compilation pour des raisons de problème d’accès aux méthodes ? Identifiez-les à l’aide de leur numéro.
  2. Quelle sera la sortie produite par ce programme si on met en commentaire toutes les lignes qui produisent un problème d’accès aux méthodes ?
    1. ______________________________________________________________
    2. ______________________________________________________________
    3. ______________________________________________________________
    4. ______________________________________________________________
    5. ______________________________________________________________
    6. ______________________________________________________________
    7. ______________________________________________________________
    8. ______________________________________________________________
    9. ______________________________________________________________
    10. ______________________________________________________________
    11. ______________________________________________________________
    12. ______________________________________________________________
    13. ______________________________________________________________
    14. ______________________________________________________________
    15. ______________________________________________________________
    16. ______________________________________________________________
    17. ______________________________________________________________
    18. ______________________________________________________________