POO_CH5 - dept-info.labri.fr
Transcription
POO_CH5 - dept-info.labri.fr
Classes abstraites Classe abstraite : (1) Elle sert de prototype à toutes les classes dérivées (2) Elle n’a pas d’objets instanciant cette classe. (3) Elle contient au moins une fonction virtuelle pure virtual Type f()=0; virtual TypeAutre p(TypeArg arg)=0; 13/01/2013 1 Classes Abstraites Forme Point Rectangle Cercle Sphère 2 1 Classe abstraite (1) class Forme{ protected: double x; double y; public: //Pas de constructeur virtual void affiche()=0; void deplace(double dx,double dy){x=x+dx;y=y+dy;} }; class Point:public Forme{ public: Point(double _x=0.0, double _y=0.0){x=_x;y=_y;}; #include <iostream.h> #include "GeometrieAbstr.hpp" int main(){ Point p(3.0,5.0); Point * pP=&p; Cercle C(6.0,7.0,8.0); Cercle *pC=&C; pP->affiche(); pC->affiche(); pC->deplace(0.5,0.5); pC->affiche(); return 0; } virtual void affiche() {cout<<"Affiche point x="<<x<<" y="<<y<<endl;} Méthode virtuelle pure }; class Cercle : public Point{ protected: double rayon; public: Cercle(double _x, double _y, double _r):Point(_x,_y){rayon=_r;} virtual void affiche(){cout<<"Afficne Cercle x="<<x<<" y="<<y<<" r="<<rayon<<endl;} Méthode concrète 3 };… Classe abstraite (2) class Forme{ protected: double x; double y; public: //Constructeur Forme(double _x=0.0, double _y=0.0){x=_x;y=_y;} virtual void affiche()=0; void deplace(double dx,double dy){x=x+dx;y=y+dy;} }; class Point:public Forme{ public: Point(double _x=0.0, double _y=0.0):Forme(_x,_y){} virtual void affiche() {cout<<"Affiche point x="<<x<<" y="<<y<<endl;} #include <iostream.h> #include "GeometrieAbstr.hpp" int main(){ Point p(3.0,5.0); Point * pP=&p; Cercle C(6.0,7.0,8.0); Cercle *pC=&C; pP->affiche(); pC->affiche(); pC->deplace(0.5,0.5); pC->affiche(); return 0; } Résultats? }; class Cercle : public Point{ protected: double rayon; public: Cercle(double _x, double _y, double _r):Point(_x,_y){rayon=_r;} virtual void affiche(){cout<<"Afficne Cercle x="<<x<<" y="<<y<<" r="<<rayon<<endl;} };… 4 2 Classe abstraite (2) class Forme{ protected: double x; double y; public: //Constructeur Forme(double _x=0.0, double _y=0.0){x=_x;y=_y;} virtual void affiche()=0; void deplace(double dx,double dy){x=x+dx;y=y+dy;} }; class Point:public Forme{ public: Point(double _x=0.0, double _y=0.0):Forme(_x,_y){} virtual void affiche() {cout<<"Affiche point x="<<x<<" y="<<y<<endl;} }; class Cercle : public Point{ protected: double rayon; public: Cercle(double _x, double _y, double _r):Point(_x,_y){rayon=_r;} virtual void affiche(){cout<<"Afficne Cercle x="<<x<<" y="<<y<<" r="<<rayon<<endl;} #include <iostream.h> #include "GeometrieAbstr.hpp" int main(){ Forme f(0.1,0.1);// Objet d’une classe abstraite Point p(3.0,5.0); Point * pP=&p; … } Forme' : cannot instantiate abstract class due to following members: d:\pédagogiebx\poo\geometrieabstr.hpp(1) : see declaration of 'Forme' D:\PédagogieBx\POO\GeometrieAbstr.cpp(4) : warning C4259: 'void __thiscall Forme::affiche(void)' : pure virtual function was not defined d:\pédagogiebx\poo\geometrieabstr.hpp(8) : see declaration of 'affiche' D:\PédagogieBx\POO\GeometrieAbstr.cpp(4) : error C2259: 'Forme' : cannot instantiate abstract class due to following members: d:\pédagogiebx\poo\geometrieabstr.hpp(1) : see declaration of 'Forme' D:\PédagogieBx\POO\GeometrieAbstr.cpp(4) : warning C4259: 'void __thiscall Forme::affiche(void)' : pure virtual function was not defined 5 };… Classe abstraite – méthodes virtuelles Une fonction déclarée virtuelle dans une classe de base doit être -redéfinie (avec les mêmes arguments!) dans la classe dérivée ou -elle reste virtuelle pure dans la classe dérivée En Java – la définition des classes abstraites par le qualificatif « abstract » 13/01/2013 6 3 Classes Abstraites(3). Forme Cercle Rectangle 7 Classe abstraite (3). Methode concrete utilise des méthodes virtuelles class Forme{ protected: double x; double y;//centre de gravité de la Forme dans un repère public: Forme(double _x=0.0, double _y=0.0){x=_x;y=_y;} //Pas de constructeur! virtual void affiche()=0; virtual double surface()=0; virtual double perimetre()=0; double facteur_compacite(){ return perimetre()/surface();} }; class Cercle : public Forme{ protected: double rayon; public: Cercle(double _x, double _y, double _r):Forme(_x,_y){rayon=_r;} virtual void affiche(){cout<<"Afficne Cercle x="<<x<<" y="<<y<<" r="<<rayon<<endl;} double surface(){return 3.1416*rayon*rayon;} //Pas de mot-clé virtual! double perimetre(){return 2*3.1416*rayon;} };//La suite est à droite! class Rectangle : public Forme{ protected: double a,b; public: Rectangle (double _x, double _y, double _a, double _b):Forme(_x,_y){a=_a;b=_b;} virtual void affiche(){cout<<"Affiche Rectangle"<<" x="<<x<<" y="<<y<<" a="<<a<<"b ="<<b<<endl;} double surface(){return a*b;} //Pas de mot-clé virtual! double perimetre(){return 2*(a+b);} }; Fichier Geomertie VirtualUse.CPP #include <iostream.h> #include "GeometrieVirtualUse.hpp" int main(){ Cercle C(6.0,7.0,8.0); Rectangle R(2.0,3.0,4.0,5.0); C.affiche(); R.affiche(); cout<<"Cercle fc= "<<C.facteur_compacite()<<endl; cout<<"Rectangle fc= "<<R.facteur_compacite()<<endl; return 0; } 8 4 Amitié en C++ : Fonctions et Classes Amies Hors l’héritage il peut être nécessaire de prévoir les passerelles entre les classes Fonctions-amies : peuvent accéder aux informations encapsulées. Typologie : fonction indépendante, amie d’une classe, fonction membre d’une classe, amie d’une autre classe, fonction amie de plusieurs classes, Toutes les fonctions membres d’une classe, amies d’une autre classe 13/01/2013 9 Amie indépendante d’une classe class Point{ private: #include <iostream.h> #include "FonctionAmie.hpp" double x; double y; public: Point(double _x=0.0, double _y=0.0){x=_x;y=_y;} void affiche(){cout<<"Je suis un point x="<<x<<" y="<<y<<endl;} //déclaration fonction amie indépendante friend int coincide (Point p,Point q); }; Intérêt : accès aux données privées des objets de la classe Passage des objets est réalisé par valeur, Il est possible par référence int coincide (Point p, Point q) {return (int)((p.x==q.x)&&(p.y==q.y));} int main(){ Point P(0.1,0.2); Point Q(0.1,0.2); if(coincide(P,Q)) cout<<"P et Q coincident test par leur amie "<<endl; else cout<<"P et Q sont différents - test pa leur amie"<<endl; return 0; } Résultat P et Q coincident – test par leur amie “Bienfaiteur” des malheureux 10 5 Fonction amie de plusieurs classes class Heure; class Date{ private: #include <iostream.h> #include "FonctionAmieCL.hpp" unsigned j,m,a; public: Date(unsigned _j, unsigned _m, unsigned _a){j=_j;m=_m;a=_a;} friend void affiche_moment(Date,Heure); //déclaration fonction amie void affiche_moment(Date _d,Heure _h){ cout<<"Date : j="<<_d.j<<" m="<<_d.m<<" a de grace ="<<_d.a<<endl; cout<<"Heure : h="<<_h.h<<" min="<<_h.m<<" sec="<<_h.s<<endl; } }; int main(){ Date Aujourdhui(25,2,2004); Heure Maintenant(16,15,50); affiche_moment(Aujourdhui, Maintenant); return 0; class Heure{ private: unsigned h,m,s; public: Heure(unsigned _h, unsigned _m, unsigned _s){h=_h;m=_m;s=_s;} friend void affiche_moment(Date,Heure); }; } “Cousine Betty” 11 Classes -amies Toutes les fonctions d’une classe sont des amies d’une autre classe Pourquoi(?): elles peuvent accéder aux données privées d’une autre classe Héritage et amitié (?) 13/01/2013 12 6 Classes-amies class Distance; class Point{ friend class Distance; private: double x; double y;//centre de gravité de la Forme dans un repère public: Point(double _x=0.0, double _y=0.0){x=_x;y=_y;} void affiche(){cout<<"Je suis un point x="<<x<<" y="<<y<<endl;} #include <iostream.h> #include "FonctionAmie.hpp" int main(){ Point P(1.1,2.2); Point Q(3.1,2.2); Distance PQ(P,Q); PQ.affiche(); return 0; } « Thibault et Fontanin » }; class Distance{ private: double d; public: Distance(double _d){d=_d;} Distance(Point P, Point Q) {d=((P.x-Q.x)*(P.x-Q.x)+(P.y-Q.y)*(P.yQ.y));} void affiche(){cout<<"Distance="<<d<<endl;} 13 Héritage et amitié class Father; class Mother{ friend class Father; protected: int a; public: class Son: public Father{ protected: int b; public: Son(int _a, int _b):Father(_a){b=_b;} }; Mother(int _a){a=_a;} }; class Dotter:public Mother{ protected: int b; public: Dotter(int _a, int _b):Mother(_a){b=_b;} }; class Father{ protected: int a; #include<iostream.h> #include "HeritageAmitie.h" int main(){ Father f(2); Son s(3,4); Mother m(2); Dotter d(5,6); f.aff(m); f.aff(d); return 0; } public: Father(int _a){a=_a;} void aff(Mother wife){cout<<"Affichage de l'epouse a= "<<wife.a<<endl;} void aff(Dotter girlfriend){cout<<"Affichage de copine a="<<girlfriend.a<<endl;} }; //La suite est à gauche On peut acceder à la partie déclaré en amitié! 14 7 Héritage et amitié class Father; class Mother{ friend class Father; protected: int a; public: Mother(int _a){a=_a;} }; class Son: public Father{ protected: int b; public: Son(int _a, int _b):Father(_a){b=_b;} void aff(Mother M){cout<<"M.a="<<M.a<<endl;} //cannot access protected member declared in class 'Mother' }; class Dotter:public Mother{ protected: int b; public: Dotter(int _a, int _b):Mother(_a){b=_b;} }; class Father{ protected: int a; public: Father(int _a){a=_a;} void aff(Mother wife){cout<<"Affichage de l'epouse a= "<<wife.a<<endl;} void aff(Dotter girlfriend){cout<<"Affichage de copine a="<<girlfriend.a<<endl;} void aff(Dotter girlfriend){cout<<"Affichage de copine b="<<girlfriend.b<<endl;}//Erreur }; //La suite est à gauche #include<iostream.h> #include "HeritageAmitie.h" int main(){ Father f(2); Son s(3,4); Mother m(2); Dotter d(5,6); f.aff(m); f.aff(d); return 0; } On ne peut pas hériter un ami! On ne peut pas toucher à la partie 15 non-partagée 8