Correction
Série Notée (Bonus)
Sujet 1
Note: 15 points sur 80 étaient facultatifs.
Exercice 1 : Bases de la POO, Héritage, Polymorphisme
Quelques remarques (suite à des erreurs/maladresses dans les copies):
- le concept d'héritage est encore parfois mal compris :
- certain définissent dans la super-classe les attributs prévus dans les sous-classes, d'autres redéfinissent dans les sous-classes des attributs déjà hérités des super-classes!
- si dans une classe, une méthode utilise un attribut, il ne faut pas lui passer l'attribut en paramètre. Les attributs d'une classe sont directement utilisables par les méthodes de cette classe.
- l'utilisation de this n'est pas une nécessité;
- le codage des constructeurs pose encore parfois problème: étudiez le corrigé
... et voici donc enfin un codage possible :
#include <iostream> #include <string> #include <cmath> using namespace std; const int MAX_X(100); const int MAX_Y(100); const int MEETING_RADIUS(3); /* Une classe pour représenter les animaux * */ class Animal{ public: Animal(int x, int y); int get_x() const ; int get_y() const; void right(unsigned int); void left(unsigned int); void up(unsigned int); void down(unsigned int); // il est mieux de la definir en virtuelle pure // car on ne sait pas a ce stade qui va etre un predateur // ou une proie virtual bool isPrey() const = 0; virtual string getName() const {return "Animal";}; void setSick(bool sick_) { sick = sick_; } void die() { dead = true; } bool isSick() const { return sick; } bool isDead() const { return dead; } // methode virtuelle pure // gerant les interactions entre animaux virtual void meet(Animal*) = 0; //teste si deux animaux peuvent interagir bool canMeet(Animal*) const; double distanceTo(const Animal&) const; protected: int x; int y; bool sick; bool dead; }; /* Une sous-classe pour les proies */ class Prey : public Animal { public: Prey(int x, int y); bool isPrey() const { return true; } string getName() const { return "Proie"; } void meet(Animal*); }; /* Une sous-classe pour les predateurs */ class Predator : public Animal{ public: Predator(int x, int y); bool isPrey() const {return false; } void meet(Animal*); string getName() const { return "Predateur"; } }; Animal::Animal(int x_, int y_) : x(x_), y(y_), sick(false), dead(false) { // Attention aux conditions limites if(x > MAX_X) x = MAX_X; if(x < 0) x = 0; if(y > MAX_Y) y = MAX_Y; if(y < 0) y = 0; } int Animal::get_x() const { return x; } int Animal::get_y() const{ return y; } void Animal::right(unsigned int units){ x += units; if(x > MAX_X) x = MAX_X; } void Animal::left(unsigned int units){ x -= units; if(x < 0) x = 0; } void Animal::up(unsigned int units){ y += units; if(y > MAX_Y) y = MAX_Y; } void Animal::down(unsigned int units){ y -= units; if(y < 0) y = 0; } // calcule la distance d'un animal a un autre double Animal::distanceTo(const Animal& otherAnimal) const { return sqrt(pow((x-otherAnimal.get_x()),2) + pow((y-otherAnimal.get_y()),2)); } // pour un affichage polymorphique : on utilise la virtualit'e des methodes // appel'ees ostream& operator<<(ostream& out, Animal& animal){ out << animal.getName() << " en ("<< animal.get_x() << ',' << animal.get_y() << ')'; if (animal.isDead()) out << ": animal mort"; else if (animal.isSick()) out << ": animal malade"; else out << ": animal sain"; return out; } Prey::Prey(int x, int y) : Animal(x,y){} bool Animal::canMeet(Animal* otherAnimal) const { return (!isDead() && !(otherAnimal->isDead()) && distanceTo(*otherAnimal) <= MEETING_RADIUS); } void Prey::meet(Animal* otherAnimal){ if (canMeet(otherAnimal)) { if (!otherAnimal->isPrey() && !isSick()) { die(); } } } Predator::Predator(int x, int y) : Animal(x,y) {} void Predator::meet(Animal* otherAnimal){ if (canMeet(otherAnimal)) { if (otherAnimal->isPrey() && !otherAnimal->isSick()) { otherAnimal->die(); } } } //PROGRAMME PRINCIPAL (fourni) int main(){ /* TEST1 */ cout << "Test de la partie 1 :" <<endl; cout << "--------------------" << endl; Animal* animal1(new Predator(0,0)); Animal* animal2(new Prey(25,0)); Animal* animal3(new Predator(10000,100000)); Animal* animal4(new Prey(-200,100000)); cout << *animal1 << endl; cout << *animal2 << endl; cout << "Distance : "; cout << animal1->distanceTo(*animal2) << endl; cout << *animal3 << endl; cout << *animal4 << endl; animal1->setSick(true); cout << *animal1 << endl; animal1->up(10000); cout << *animal1 << endl; animal1->left(200); cout << *animal1 << endl; animal1->die(); cout << *animal1 << endl; delete animal1; delete animal2; delete animal3; delete animal4; /*FIN TEST 1*/ /* TEST2 */ cout << endl; cout << "Test de la partie 2:" <<endl; cout << "--------------------" << endl; cout << "Proie saine, Predateur trop eloignes :" << endl; animal1 = new Prey(0,0); animal2 = new Predator(5,5); cout << *animal1 << endl; cout << *animal2 << endl; cout << "apres tentative de rencontre : " << endl; animal1->meet(animal2); cout << *animal1 << endl; cout << *animal2 << endl; cout << endl; cout << "Proie malade, Predateur se rencontrent :" << endl; animal1->setSick(true); animal2->left(4); animal2->down(4); cout << *animal1 << endl; cout << *animal2 << endl; cout << "apres rencontre (dans les deux sens): " << endl; animal1->meet(animal2); cout << *animal1 << endl; cout << *animal2 << endl; animal2->meet(animal1); cout << *animal2 << endl; cout << *animal1 << endl; cout << endl; cout << "Proie saine, Predateur se rencontrent :" << endl; animal1->setSick(false); animal2->setSick(false); cout << *animal1 << endl; cout << *animal2 << endl; cout << "apres rencontre :" << endl; animal1->meet(animal2); cout << *animal1 << endl; cout << *animal2 << endl; cout << endl; cout << "Predateur, Proie saine se rencontrent :" << endl; animal3 = new Prey(2,2); cout << *animal2 << endl; cout << *animal3<< endl; cout << "apres rencontre :" << endl; animal2->meet(animal3); cout << *animal2 << endl; cout << *animal3 << endl; cout << endl; delete animal1; animal1 = 0; delete animal2; animal2 = 0; delete animal3; animal3 = 0; cout << "Deux proies saines de rencontrent:" << endl; animal1 = new Prey(20,20); animal2 = new Prey(10,10); animal2->up(8); animal2->right(8); cout << *animal1 << endl; cout << *animal2 << endl; cout << "apres rencontre : " << endl; animal1->meet(animal2); cout << *animal1 << endl; cout << *animal2 << endl; cout << endl; delete animal1; animal1 = 0; delete animal2; animal2 = 0; cout << "Deux predateurs se rencontrent:" << endl; animal1 = new Predator(20,20); animal2 = new Predator(10,10); animal2->up(8); animal2->right(8); cout << *animal1 << endl; cout << *animal2 << endl; cout << "apres rencontre :" << endl; animal1->meet(animal2); cout << *animal1 << endl; cout << *animal2 << endl; delete animal1; animal1 = 0; delete animal2; animal2 = 0; /* FIN TEST2*/ return 0; }
Exercice 2: durée de vie des variables
#include <iostream> #include<vector> #include<string> using namespace std; class Composant { public: Composant(string nom, double quantite) :nom_(nom), quantite_(quantite) {} void afficher(ostream& out) const { out << nom_ << " " << quantite_ << endl; } private: string nom_; double quantite_; }; class Dosage : public vector<Composant*> { public: /* * le probleme est du au fait que cette methode ajoute au vecteur * l'adresse d'une variable locale. * Cette variable etant detruite a la fin de l'execution de la methode * le pointeur stock'e dans la collection sera invalide */ void ajouter_composant(string nom, double quantite) { Composant c(nom, quantite); push_back(&c); /* Solution: allocation dynamique push_back(new Composant(nom,quantite)); */ } void afficher(ostream& out) const { for (int i(0); i < size(); ++i) (*this)[i]->afficher(out); } void vider() { for (int i(0); i < size(); ++i) delete (*this)[i]; clear(); } }; int main() { Dosage d; d.ajouter_composant("alcool", 0.3); d.ajouter_composant("formol", 0.4); d.afficher(cout); d.vider(); return 0; }