UNIVERSITE DE LA MANOUBA -----¤¤¤¤-----
ECOLE NATIONALE DES SCIENCES DE L'INFORMATIQUE
Matière : POO Classe : I.I. 1A A-U : 2016-2017
Série N°4 – Polymorphisme en C++
class B : public A { public: B(){cout<<"B::B()"<<endl;} ~B(){cout<< "B:: ~B()"<<endl;} void f1() {cout << " B::f1()" << endl;} virtual void f2() {cout << " B::f2()" << endl;} } ;
Exercice n°1 Soit le code C++ comportant les classes A et B suivantes : class A { public: A(){cout<<"A::A()"<<endl;} virtual ~A() { cout<< "A:: ~A()"<<endl;} virtual void f1() {cout << "A::F1()" << endl;} void f2(){cout << " A::f2()" << endl;} }; 1. Quel est le résultat d’affichage du code suivant ? void main(){ B obj; } 2. Quelle est la différence entre une méthode virtuelle et une méthode non virtuelle au niveau de la convention d'appel ? 3. Quel est le résultat d’affichage du code suivant ? void main() {B *pB = new B; A *pA = pB; pA->f1(); pB->f2(); pB->f1(); pA->f2();} Exercice n°2 Soit le code c++ suivant : class Figure{ public : Figure(string nom) : nom_(nom) { } string getNom() const { return nom_; } virtual void intersection(const Figure& f) const = 0; virtual void intersection(const Cercle& c) const = 0; virtual void intersection(const Rectangle& r) const = 0; private: string nom_;}; class Cercle : public Figure{ public : Cercle(string nom) : Figure(nom) { } virtual void intersection(const Figure& f) const; virtual void intersection(const Cercle& c) const; virtual void intersection(const Rectangle& r) const;}; void Cercle::intersection(const Cercle& c) const {cout << "Inter. cercle " << getNom() << " et cercle " <<c.getNom() <<endl;} void Cercle::intersection(const Rectangle& r) const {cout << "Inter. cercle " << getNom() << " et rectangle " <<r.getNom()<< endl;} void Cercle::intersection(const Figure& f) const{f.intersection(*this);} class Rectangle : public Figure{ public : Rectangle(string nom) : Figure(nom) { } virtual void intersection(const Figure& f) const; virtual void intersection(const Cercle& c) const; virtual void intersection(const Rectangle& r) const; }; void Rectangle::intersection(const Cercle& c) const{cout << "Inter. rectangle " << getNom() << " et cercle " <<c.getNom()<< endl;} void Rectangle::intersection(const Rectangle& r) const {cout << "Inter. rectangle " << getNom() << " et rectangle " <<r.getNom() << endl;} void Rectangle::intersection(const Figure& f) const {f.intersection(*this);} 1. Donnez l’arborescence des classes définies précédemment. 2. On vous demande de donner l’affichage obtenu lors de l’exécution du programme suivant : void main(){
1/3
Cercle c1("C1"); Cercle c2("C2"); Rectangle r1("R1"); Rectangle r2("R2"); Figure* ptr1 = new Cercle("C3"); Figure* ptr2 = new Rectangle("R3"); cout << "Ligne 1" << endl; c1.intersection(c2); cout << "Ligne 2" << endl; ptr1->intersection(r1); cout << "Ligne 3" << endl; c2.intersection(*ptr2); cout << "Ligne 4" << endl; ptr2->intersection(*ptr1); delete ptr1; delete ptr2; } Exercice 3 Soit le code C++ suivant : Soit les deux classes Process et Thread suivantes : class Process{ int pid; public: Process( ) { pid = 0; cout<<"Process Defaut"<<endl; } Process(Process& cout<<"Process Copie\n"; Process(int x) { pid = x; cout<<"Process Param"<<endl; } ~Process() { Destructeur"<<endl; } virtual void imprimer() {cout << "pid="<< pid << endl;} }; class Thread : public Process{ int tid; Process p; public: Thread():Process() { tid=0; cout<<"Thread Defaut\n"; } Thread( int cout<<"Thread Param\n"; } ~Thread() Destructeur"<<endl;} void imprimer() { cout << "tid=" << tid << endl; } };
Publicité
{cout<<"Thread
cout<<"Process
v):Process(v)
pid=B.pid
tid=1;
B)
;
{
Publicité
{
void Fonction(Thread x) { x.imprimer();} Process obj_pro1; int main( ) {Thread obj_thr1(2); Process *ptr_pro = new Process [2]; ptr_pro[0].imprimer(); delete [] ptr_pro; obj_thr1.imprimer(); ptr_pro = &obj_thr1; ptr_pro->imprimer(); obj_thr1.Process::imprimer(); Process obj_pro2(obj_pro1); obj_pro2.imprimer(); Fonction(obj_thr1);
return 0;}
1. Pour chacune des instructions de la fonction main(), indiquez ce qui sera affiché à l’écran. 2. Ajouter le constructeur de recopie de la classe Thread qui doit contenir l’instruction « cout<<"Thread Copie \n » et donner le nouveau affichage de l’instruction suivante : Fonction(obj_thr1) ;
Exercice 4 Une entreprise de Patagonie développe un moteur à huile de rutabaga, et dote plusieurs véhicules de ce moteur. Avant d'effectuer des tests grandeur nature, l'entreprise conçoit un programme de simulation du comportement des véhicules. Ce programme sera écrit en C++. On ne s'intéresse dans cet exercice qu'à une toute petite partie de ce programme. Le problème que l'on veut résoudre dans un premier temps est celui de la représentation des véhicules et du calcul de la vitesse maximum pouvant être atteinte par un véhicule. Tout ‘véhicule’ possède une immatriculation (chaîne de caractères) et un poids à vide (réel). Certains véhicules peuvent transporter un chargement : on appelle alors charge le poids de ce chargement. La charge d'un véhicule ne doit pas dépasser un certain poids, que l'on appellera charge maximale, dépendant du type de véhicule. Les différents
2/3
types de véhicules dotés du fameux moteur sont les suivants : les petits bus, les camions citernes, et les camions bâchés. • la classe ‘petit_ bus’ a un poids à vide de 4 tonnes, et peut atteindre une vitesse maximale de 150 km/h. Il ne possède pas de chargement (le poids des passagers est considéré comme négligeable par rapport au poids à vide). • la classe ‘camion_citerne’ a un poids à vide de 3 tonnes et une charge maximale de 10 tonnes. Sa vitesse maximale dépend de sa charge : - 130 km/h si la charge est nulle - 110 km/h si la charge est inférieure ou égale à 1 tonne - 90 km/h si la charge est supérieure à 1 tonne et inférieure ou égale à 4 tonnes - 80 km/h pour une charge supérieure à 4 tonnes.
• la classe ‘camion_bâché’ a un poids à vide de 4 tonnes et une charge maximum de 20 tonnes. Sa vitesse maximale dépend également de sa charge (mais à charge égale, un camion citerne a une vitesse maximale plus faible, car le liquide qu'il transporte est plus instable qu'un chargement solide):
Publicité
- 130 km/h si la charge est nulle - 110 km/h si la charge est inférieure ou égale à 3 tonnes - 90 km/h si la charge est supérieure à 3 tonnes et inférieure ou égale à 7 tonnes - 80 km/h au delà. Les classes ‘véhicule’, ‘petit_ bus’, ‘camion_citerne’, ‘camion_bâché’ possèdent une méthode affichage ‘affichage’ permettant d’afficher les caractéristiques de chaque véhicule. Les ingénieurs de l'entreprise fournissent une formule permettant de calculer la consommation de carburant d'un véhicule en fonction de sa vitesse et de son poids total (poids à vide + charge éventuelle) consommation = (vitesse-en-km/h)/10 + (poids_total-en-tonnes). Cette formule est la même pour tous les types de véhicules, la méthode au calcul de consommation de carburant correspondante est : float consommation (int v, int p), qui retourne la consommation (en litres pour 100 km) d'un véhicule de poids p allant à une vitesse v. Question 1
Donnez l’interface et l’implémentation des classes ‘Véhicule’, ‘petit_bus’, ‘camion_citerne’, ‘camion_bâché’. Question 2 On s'intéresse maintenant à la définition d'une classe Convoi, permettant de gérer un convoi de véhicules. Cette classe contient une collection de véhicules hétérogènes. L’ajout des véhicules se fait toujours à la fin. La classe Convoi doit savoir calculer la vitesse maximale d'un convoi, sachant que cette vitesse correspond à la plus petite des vitesses maximales des véhicules du convoi. Cette classe possède aussi les méthodes permettant l’ajout et la suppression de véhicules. Donnez l’interface et l’implémentation de la classe ‘Convoi’ (pensez à utiliser le conteneur Vector de STL). Question 3 Donnez la partie du code permettant de :
a) créer un convoi ‘C’, b) créer deux camions bâchés c) créer un petit bus d) créer trois camions citerne e) ajouter ces véhicules à ‘C’ f) afficher les descriptions et la vitesse maximale de chaque véhicule de ‘C’.
3/3