Vous êtes sur la page 1sur 8

[C++] TP 3

1. Héritage simple public

1.1. Illustration

Définir une classe Mere dont le constructeur et le destructeur affichent quelque chose à
l'écran (comme la classe Bavarde ).
Définir une classe Fille qui hérite (publiquement) de Mere . Ne rien mettre pour l'instant
dans cette classe.
Instancier une classe Fille . Que se passe-t-il ?


Pour mieux observer le phénomène, implémenter un constructeur et un destructeur
"bavards" pour la classe Fille .
Si le constructeur de Fille ne mentionne pas celui de Mere , que se passe-t-il ?


Modifier le constructeur par défaut de Fille pour qu'il appelle explicitement celui de
Mere
Ajouter un attribut entier dans la classe Mere

/
Vérifier la visibilité de celui-ci dans une méthode de la classe Fille s'il est privé, protégé
ou public. Par la suite, on considérera cet attribut non public.
Utiliser cet attribut pour compter le nombre d'instances de Mere qui sont créées (ce
nombre sera affiché à l'instanciation)
Vérifier que ce nombre est bien incrémenté à l'instanciation d'une classe Fille .


Ajouter une méthode getAttribut() (getter) sur cet attribut entier
Appeler cette méthode à partir d'un objet de la classe Mere , puis d'objet de la classe
Fille .


Ajouter un attribut nom de type chaine de caractères à la classe Mere
Ajouter un constructeur qui permet d'initialiser cet attribut
Ajouter une méthode get() sur cet attribut
Instancier un objet de la classe Mere avec ce constructeur
Appeler cette méthode à partir d'un objet de la classe Mere , puis d'objet de la classe
Fille .
Essayer d'instancier un objet de la classe Fille dont le nom est donné à l'initialisation,
que se passe-t-il ?


Écrire un constructeur de Fille qui prend en paramètre une chaîne de caractères et qui
appelle explicitement celui de la classe Mere .
Que se passe-t-il si le constructeur de Mere avec la chaîne de caractères n'est pas
spécifié ?
Ajouter maintenant une méthode afficher() dans la classe Mere qui affiche sur la
sortie standard que l'objet est de classe Mere
Faire de même pour la classe Fille
Vérifier que l'exécution est correcte pour une instance de Mere et une instance de
Fille
Vérifier maintenant que l'exécution est correcte pour le code ci-dessous. Si ce n'est pas le
cas, corriger votre code pour que cela marche

/
1 Mere *pm = new Mere("mere_dyn");
2 Fille *pf = new Fille("fille_dyn");
3 Mere *pp = new Fille("fille vue comme mere");
4 pm->afficher(); // affiche Mere
5 pf->afficher(); // affiche Fille
6 pp->afficher(); // affiche Fille

1.2. Une petite question ...

Que fait le programme suivant ?

1 class Mere {
2 protected:
3 string nom;
4 public:
5 Mere(string s="pas fourni"):nom(s) {
6 }
7
8 void methode1() {
9 cout << "Nom" << nom << endl;
10 }
11 };
12
13 class Fille : public Mere {
14 private:
15 string nom;
16 public:
17
18 Fille():Mere("noname") {
19 }
20
21 void methode2() {
22 cout << "Afficher2" << nom << endl;
23 }
24 };
25
26 int main(int, char**) {
27 Fille f;
28
29 f.methode1();
30 f.methode2();
31 }

/
2. Messages

Cet exercice n'est pas difficile au niveau de la modélisation mais il est nécessaire de

 bien séparer la déclaration de l'implémentation. Vous ne devez pas y passer plus de


10 minutes

Écrire deux classes A et B . La classe A possède un entier i , et la classe B un entier j .


Ces deux classes ont chacune une méthode exec() et une méthode send() qui leur permet
d’envoyer un message à un objet de l’autre classe.

La méthode send() de la classe A accepte un pointeur sur un objet de classe B et


réciproquement.
La méthode exec() de chaque classe accepte un entier en paramètre et ajoute la valeur
de cet entier aux attributs i ou j selon la classe de l’objet concerné ( A ou B ).

L’exécution du corps d’une méthode send() lance un exec() sur l’objet distant avec une
constante de votre choix. Ainsi unA.send(&unB) active la méthode send() de la classe A
qui lance la méthode exec() de la classe B .

Pour que cet exercice soit formateur, il faut :

Créer les fichiers A.hpp, A.cpp, B.hpp, B.cpp et main.cpp


les déclarations des classes doivent être correctes dans les fichiers d'entête avec des
gardiens
Utiiliser les déclarations anticipées (encore appelées forward) des classes.

3. Exercice de modélisation

Nous voulons rendre service à un personne qui fait des statistiques sur des données provenant
de différentes sources (des producteurs).

Déclarer une classe Producteur avec un attribut travail . L'attribut donne le nombre
de fois où la méthode produire() a été appelée.

Ajouter une méthode produire() qui prend en paramètre un entier (un nombre de
nombres à générer) et une chaîne de caractères correspondant au fichier à écrire.
Écrire l'implémentation de la méthode produire() où la méthode génère les premiers
entiers (le fichier résulat mentionne d'abord le nombre d'éléments puis les éléments un à
un)
Créer maintenant une classe Statisticien qui disposera d'une méthode acquerir()
avec un paramètre, le nom du fichier à lire. La classe sera dotée d'un attribut calcul qui
sera vrai si des calculs sont disponibles et faux sinon.

Implémenter la méthode acquerir() , la méthode lit les nombres du fichier et calcule


différentes choses : on s'intéressera à la somme et la moyenne. On pourra par exemple
vérifier que la lecture est cohérente avec l'écriture. La somme des n premiers entiers est
n*(n+1)/2. Je vous laisse écrire le code de test !
Écrire maintenant une nouvelle classe ProducteurAleatoire où les nombres générés
le sont aléatoirement

Modifier la hiérachie de classe pour que la classe Producteur soit maintenant abstraite
et que la classe ProducteurPremiersEntiers fasse ce que la classe Producteur
faisait avant.
Vérifier que l'instanciation de la classe Producteur n'est pas possible. On ne peut pas
vérifier cela avec les tests unitaires

Nous allons continuer l'application fil rouge.

Créer une classe Liste qui a pour attributs deux tableaux : un de Cercle et un de
Rectangle de capacité fixe (une constante vraie const , PAS une constante
symbolique). Ces attributs sont publics, ce n'est pas très beau mais relativement
nécessaire. Si vous voulez respecter l'encapsulation, utilisez des tableaux de pointeurs.
On connaitra également le nombre d'éléments vraiment placés dans chaque tableau (leur
"taille").

Liste

/
+ cercles : tableau
+ nb_c : entier
+ rectangles : tableau
+ nb_r : entier
+ compteur : entier

+ Liste()
+ getCompteur() : entier
+ toString() : chaine

Ajouter aux classes Rectangle et Cercle un nouvel attribut ordre . Cet attribut sera
initialisé par l'objet Liste à chaque fois qu'un objet est ajouté. On suppose évidemment
qu'un objet ne peut appartenir qu'à une seule liste à la fois.
Proposer une méthode toString() qui renvoie dans une chaîne de caractères la liste
des rectangles et des cercles contenus dans la liste. Vous pourrez afficher les listes une
par une mais à la fin, il faudra afficher les éléments dans l'ordre où ils sont été ajoutés.

Cette manière de stocker les objets n'est ni pratique ni efficace, le C++ nous permet
 de faire bien mieux avec le modèle objet, ce que l'on fera plus tard !

Créer une classe Point qui a pour propriété une abscisse x et une ordonnée y
Créer une classe Forme qui a pour propriété un point, une largeur w et une hauteur h
Ajouter un attribut de classe nbFormes qui est incrémenté à chaque fois qu'un objet
Forme est construit.
Vérifier bien entendu que l'instanciation d'une forme se passe bien et est cohérente avec
l'attribut de classe.

Vous aimerez peut-être aussi