IFT 1166 --- DEMO #9
Contenu
préparation au TP3
Utilisation du patron de classe défini en demo #7
Héritage simple, public Typage statique / typage dynamique
Exercice
a) Définissez une classe <Partition> en utlisant le
patron de classe <List> de la démonstration 7. Vous vous appuierez
sur le fait qu' une partition peut être vue comme une liste de notes,
une note étant par exemple donnée par une fréquence
(en Hz) et une durée (en ms).
Il est vous est donné libre choix de définir d'autres
classes (par exemple une classe note) pour y parvenir. Le but de la classe
Partition étant simplement de fournir une interface simple permettant
au moins d'ajouter une note, et d'afficher les notes rentrées.
b) Soit une classe de base <Instrument>
class Instrument {
int tessiture; // nombre d'octaves que l'on peut
produire avec l'instrument
int tonalite; // tonalite de l'instrument
(Hz)
string nom; // nom de l'instrument
public:
Instrument(string n, int t=0, int ton=0) {
cout << "
constructeur Instrument\n";
nom = n;
tessiture = t;
tonalite = ton;
}
Instrument(const Instrument & I); // pas vraiment
necessaire ici, mais illustratif
Instrument & Instrument::operator= (const Instrument
& I); // pas vraiment necessaire ici, mais illustratif
void jouer(Partition &p) {
cout << "
Instrument:" << nom << " => ";
p.affiche();
}
void info() {
cout << "
info Instrument " << nom << " tessiture " << tessiture
<< " tonalite " << tonalite << endl;
}
};
Et deux classes dérivées <Cuivre> et <Corde> héritées
de la classe <Instrument> (respectivement la classe des cuivres et la
classe des instruments à cordes) et dont le squelette peut ressembler
à:
class Cuivre : public Instrument{
int justePourVoir;
public:
Cuivre (string nom);
void jouer(Partition & p) { // redifinition d'une
fct membre
cout << "
Section Cuivre , jouer:\n";
Instrument::jouer(p);
}
void infoCuivre() { // une fct specifique a la classe
Cuivre
cout << "
info Cuivre : justePourVoir=>" << justePourVoir << endl;
}
};
// ---------------------------------------------------------------
class Corde : public Instrument {
public:
Corde(string nom, int tess=0, int ton = 0); // constructeur
Corde (const Corde & C); // constructeur de
recopie
Corde & Corde::operator= (const Corde & C);
// operateur d'affectation
};
Complétez/modifez ces classes de manière à pouvoir compiler et exécuter correctement un programme principal utilisant des objets de ces classes.
c) Reprendre au besoin votre code de manière à pouvoir exécuter le programme principal qui suit. Notez que ce programme contient des erreurs de conception liées à l'héritage, qu'il convient d'identifier dans un premier temps.
// exemple de programme montrant tous les aspects de l'héritage simple public il contient des erreurs de conception à identifier
int main() {
// creation d'une "partition" de nom "random" avec
un nombre de 10 notes aleatoires
Partition p("random");
for (int i=0; i<10; i++) p.ajoute(440+(int) (200.0*rand()/(RAND_MAX+1.0)));
p.affiche(); // affichage de cette partition
// creation d'objets et de ptrs divers pour illustrer
l'heritage simple
Instrument I("Inst"),I2("Inst2"),I3("inst3",10,220),*pi;
Cuivre Cu1("Cuivre1"),Cu2("Cuivre2"),*pcu=&Cu1;
Corde Co1("Corde1"),Co2("Corde2",6,440);
// essais
I.jouer(p);
Cu1.jouer(p);
Co1.jouer(p);
cout << Cu1.tessiture;
// les conversions entre objets
cout << "conversion entre objets\n";
I = Cu1;
I.jouer(p); // le jouer de la classe Instrument
I.infoCuivre();
Cu1 = I;
// les conversions entre pointeurs dans le sens *base
= *derivee
cout << "convertion entre ptrs\n";
pi = pcu;
pi->jouer(p);
// les conversions entre pointeurs dans le sens *derivee
= *base
pcu = pi;
pi = &I2;
pi->info();
pcu = (Cuivre *) pi;
pcu->jouer(p);
pcu->info();
pcu->infoCuivre(); // ouatch !!!
// que se passe t-il avec les constructeurs de recopie
?
cout << "Testons maintenant la recopie\n";
Cuivre Cu3 = Cu2;
Cu3.info();
Corde Co3 = Co2;
Co3.info();
// que se passe t-il avec les operateurs d'affectation
?
cout << "Testons maintenant l'affectation\n";
I3.info();
I = I3;
I.info();
Cu1 = Cu2;
Cu1.info();
Co2.info();
Co1 = Co2;
Co1.info();
return 0;
}
d) Identifiez systématiquement les fonctions, les constructeurs et les opérateurs utilisés par ce programme.
e) Modifiez votre code de manière à gérer
le typage dynamique lors d'appels à des fonctions définies
dans la classe de base et dans une classe dérivée.
PS: vous pouvez remplacer <Instrument> (resp. <Cuivre> et <Cordre>)
par toute autre classe de base (resp dérivées) de votre choix.