La présentation est en train de télécharger. S'il vous plaît, attendez

La présentation est en train de télécharger. S'il vous plaît, attendez

Chapitre V Héritage ou dérivation d’une classe. 2 Héritage Permet de créer une classe à partir d’une autrei.e.la nouvelle classe bénéficie des données.

Présentations similaires


Présentation au sujet: "Chapitre V Héritage ou dérivation d’une classe. 2 Héritage Permet de créer une classe à partir d’une autrei.e.la nouvelle classe bénéficie des données."— Transcription de la présentation:

1 Chapitre V Héritage ou dérivation d’une classe

2 2 Héritage Permet de créer une classe à partir d’une autrei.e.la nouvelle classe bénéficie des données et fonctions membres de la classe dont elle dérive. Dans cette nouvelle classe, vous pourrez ensuite définir de nouveaux membres afin de modifier et spécialiser la classe de base. Technique permettant de réutiliser et de spécialiser les classes existantes : - évite de réécrire du code lorsqu’un comportement est hérité d’une autre classe; - augmente la fiabilité du code et réduit les coûts de maintenance. Partage du code : - plusieurs programmeurs ou projets peuvent utiliser les mêmes classes; - plusieurs classes développées dans un projet peuvent hériter d’une même classe; - ainsi, plusieurs types d’objets partagent le code qu’ils héritent; ce code est écrit une seule fois. Avantages de l’héritage :

3 3 Héritage Consistance des interfaces : - lorsque plusieurs classes héritent de la même super-classe, celles-ci auront les les mêmes comportements; - l’héritage permet d’unifier différents types d’objets sur la base de leurs ressemblances. Prototypage rapide : - lorsqu’on construit un système à partir de composantes réutilisables, on investit le temps de développement dans les nouvelles zones moins connues du logiciel; - permet de générer plus rapidement des prototypes de notre système. Masquage d’information : - réduction du couplage des données; - on se concentre sur la compréhension de la nature des abstractions disponibles et de leur interface; - la compréhension des mécanismes d’implantation n’est pas nécessaire à la bonne utilisation de ces composantes.

4 4 Héritage Coûts de l’héritage : Rapidité d’exécution - on ne peut espérer obtenir autant de performance avec des outils génériques qu’avec une implantation spécifique. - toutefois, la perte de performance est mineure et est compensée par une augmentation de la rapidité de développement. Dimension du code exécutable - l’utilisation de librairies réutilisables produit souvent des exécutables plus gros que les systèmes conçus spécifiquement pour un projet. - toutefois, contenir les coûts, produire de la qualité et du code exempt d’erreur est plus important. Appel de méthode - il y a un coût à payer pour un appel de méthode p/r à un appel de procédure. - toutefois, il y a un gain à utiliser la technologie OO. Complexité du programme - la sur-utilisation de l’héritage augmente la complexité.

5 5 Réutilisation Utiliser du code existant plutôt que de réécrire chaque application à partir de rien. Accélère le temps de développement. Réduit le coût de l’écriture et de la maintenance du code d’une application. Réutilisation par « recyclage » Prendre un bout de code dans un programme qui nous intéresse et l’utiliser dans un autre programme en l’adaptant. Problèmes rencontrés : Trouver le code qui nous intéresse peut être difficile. Pas d’assurance que le code provenant d’un autre programme est correct. Il peut être difficile de détacher un bout de code d’un programme à cause des nombreuses dépendances qui y sont implantées. Le bout de code extrait peut demander d’importantes modifications pour fonctionner dans le nouveau programme. Souvent plus facile de tout réécrire…

6 6 Propriétés essentielles du code réutilisable Facile à trouver et à comprendre. Assurance raisonnable que le code est correct. Ne demande pas d’effectuer une séparation du code qui le contient. Ne demande pas de changement pour être utilisé dans un nouveau programme. Mythes de la réutilisation La réutilisation résoudra la crise du logiciel. Tout le code qu’on écrit devrait être réutilisable. Il est toujours préférable de réutiliser que de coder à partir de rien. La programmation orientée objet rend facile l’écriture de code réutilisable.

7 7 Illustration du concept d’héritage Je connais bon nombre de comportements de Gilles, le fournisseur de bois, non pas parce que je sais qu’il est fournisseur de bois, mais parce qu’il est un commerçant. De ce fait, je m’attends à ce qu’il me demande de l’argent pour ses services et qu’il me donne un reçu en échange. Ces comportements sont aussi vrais pour l’épicier, le fleuriste ou le coiffeur. Étant donné que fournisseur de bois est plus spécialisé que Commerçant, ce qui est vrai pour le commerçant est vrai pour le fournisseur de bois et donc pour Gilles. En structurant nos connaissances du problème à résoudre de manière hiérarchique, cela permet une meilleure compréhension du problème.

8 8 Illustration du concept d’héritage Citoyen Commerçant Fournisseur de bois

9 9 Illustration du concept d’héritage Prêt auto Prêt hypothécaire Prêt rénovations Forme CercleTriangleRectangle Compte d’épargne Compte chèque

10 10 Hiérarchie d’héritage pour les membres d’une communauté universitaire Membre Communauté EmployéÉtudiantAncien Employé en faculté Personnel hors faculté AdministrateurEnseignant Administrateur Enseignant Étudiant employé Héritage multiple

11 11 Types d’héritage (Yves Roy) Spécialisation Spécification Construction Généralisation Extension Limitation Codes communs Forme classique d’héritage Hériter pour spécialiser Matrice carrée Matrice

12 Types d’héritage (Yves Roy) Spécialisation Spécification Construction Généralisation Extension Limitation Réalisation d’une spécification abstraite S’assurer que les héritiers auront une même interface Le parent est désigné comme classe abstraite parce qu’il définit des comportements communs sans les implanter, les héritiers le feront. Polygone Figure géométrique Cercle Opérations imposées aux figures géométriques : - Afficher- Aire - Normale- etc. Codes communs

13 13 Types d’héritage (Yves Roy) Spécialisation Spécification Construction Généralisation Extension Limitation Héritage utilitaire On veut récupérer diverses fonctionnalités du parent tout en modifiant certains paramètres ou nom de méthode. Approche à éviter : utiliser l’agrégation à la place. Pile Liste simple Une pile n’est pas une liste à laquelle on ajoute des méthodes spécifiques à la pile. La liste peut être utilisée comme attribut de la classe Pile. Codes communs

14 14 Types d’héritage (Yves Roy) Spécialisation Spécification Construction Généralisation Extension Limitation Inverse de la spécialisation Une sous-classe va créer un concept plus général que son parent en modifiant ou élargissant sa gamme de comportements. Fréquent lorsqu’on bâtit sur des classes existantes dont on ne peut pas modifier le contenu. Approche à éviter : préférable d’utiliser la spécialisation. Codes communs

15 15 Types d’héritage (Yves Roy) Spécialisation Spécification Construction Généralisation Extension Limitation Polygone Figure géométrique Cercle Librairie on ne possède pas le code source Polygone+Cercle+ Généralisation Renferme des fonctionnalités supplémentaires Codes communs

16 Chapitre V - Héritage ou dérivation d'une classe16 Types d’héritage (Yves Roy) Spécialisation Spécification Construction Généralisation Extension Limitation Héritage pour restreindre le comportement d’une sous-classe p/r au parent. Fréquent lorsqu’on bâtit sur des classes existantes dont on ne peut pas modifier le contenu. Approche à éviter. Pile Dèque Les opérations possibles sur une pile sont limitées p/r à celles d’un dèque. Il faut redéfinir les méthodes trop permissives. Codes communs

17 Chapitre V - Héritage ou dérivation d'une classe17 Types d’héritage (Yves Roy) Spécialisation Spécification Construction Généralisation Extension Limitation Des classes possèdent un code commun mais n’ont pas de lien hiérarchique. On choisit arbitrairement une des classes comme parent laquelle renfermera le code commun. Fréquent lorsqu’on bâtit sur des classes existantes dont on ne peut pas modifier le contenu. Approche à éviter : Préférable de factoriser le code commun dans une classe abstraite. Codes communs

18 Chapitre V - Héritage ou dérivation d'une classe18 Types d’héritage (Yves Roy) Spécialisation Spécification Construction Généralisation Extension Limitation Codes communs Souris Tablette graphique Il existe un code commun aux 2 classes. Il n’y a aucune raison pourquoi la tablette graphique hériterait de la souris. Périphérique d’entrée Tablette graphiqueSouris Classe abstraite Les héritiers implantent leur code spécifique.

19 Chapitre V - Héritage ou dérivation d'une classe19 Héritage en C++ La classe dont dérive une classe se nomme la classe de base, la superclasse, la classe parent, la classe ancêtre, la classe mère ou la classe père. La classe dérivée se nomme la classe fille ou la sous-classe. Chaque fois que vous créez un objet d ’une classe dérivée, C++ créera un objet de la classe de base. Par ex., si B dérive de A, un objet de B est un objet de A avec des éléments supplém. Les données membres des classes de base sont créées pour chaque objet dérivé indépendamment des directives de protection. Exemple : Si B dérive de A, et qu’une donnée membre de A est définie en privée (private), elle est allouée quand même. Elle sera utilisable par la partie A de l ’objet B et non par les méthodes spécifiques de B.

20 Chapitre V - Héritage ou dérivation d'une classe20 Héritage Ce processus de création automatique d’un objet de la classe de base, chaque fois que l’on déclare un objet de la classe dérivée, se propage tout au long de la hiérarchie. Bien distinguer entre l’utilisation de classes indépendantes et l’héritage. Mise en oeuvre class Nom_de_la_classe_derivee : Nom_de_la_classe_de_base { ….. }; désigne l ’une des 3 valeurs suivantes: public, private et protected. à venir

21 Chapitre V - Héritage ou dérivation d'une classe21 Héritage Exemple :une classe B qui dérive de la classe A. class B : public A { …… }; Note : La classe A doit obligatoirement être déclarée avant la classe B.

22 Chapitre V - Héritage ou dérivation d'une classe22 Héritage Exemple Liste_simple Polygone_2D Polygone_2D_convexe « hérite de » Exercices résolus (chap. IV)

23 Chapitre V - Héritage ou dérivation d'une classe23 Polygone_2D.h #include "Liste_simple.h" struct sommet_2D { int x, y; }; class Polygone_2D { /*Spécification fonctionnelle de la classe " Polygone_2D " Composantes :Chaque composante est un sommet du polygone 2D. Structure :Il existe une relation linéaire (structure) entre les sommets du polygone. Cette relation décrit le mode de parcours du contour polygonal dans le sens horaire.*/

24 Chapitre V - Héritage ou dérivation d'une classe24 Polygone_2D.h (suite) protected: int Nb_de_sommets;/* Nombre de sommets du polygone*/ Liste_simple Ensemble_des_sommets; float Aire_Triangle_2D(int x, int y, int u, int v, int a, int b); /*Retourne l'aire du triangle dont les coordonnées des sommets sont resp. (x, y), (u, v) et (a, b). Pré -Nil Post -Retourne l'aire du triangle 2D.*/

25 Chapitre V - Héritage ou dérivation d'une classe25 Polygone_2D.h (suite) public: Polygone_2D(); /*Permet de créer un polygone 2D à 0 sommet. Pré -L > 0. Post -Un polygone à 0 sommet est créé.*/ void Ajouter_sommet(int x, int y); /*Permet d'ajouter un sommet de coordonnées x, y au polygone. L'ordre d'insertion des sommets du polygone doit respecter un mode de parcours dans le sens horaire. Pré -Le polygone 2D a déjà été créé. Post -Un sommet de coordonnées x,y a été ajouté au polygone.*/

26 Chapitre V - Héritage ou dérivation d'une classe26 Polygone_2D.h (suite) int Nombre_de_sommets(); /*Retourne le nombre de sommets du polygone 2D. Pré -Le polygone 2D a déjà été créé. Post -Retourne le nombre de sommets.*/ void Detruire_Polygone_2D(); /*Permet de détruire les sommets du polygone 2D. Pré -Le polygone 2D a déjà été créé et renferme au moins un sommet. Post -Les sommets du polygone 2D ont été détruits. Le polygone renferme 0 sommet.*/

27 Chapitre V - Héritage ou dérivation d'une classe27 Polygone_2D.h (fin) float Aire_Polygone_2D(); /*Retourne l'aire du polygone 2D. Pré -Le polygone 2D a déjà été créé et le nombre de sommets est supérieur ou égal à 3. Post -L'aire du polygone 2D est retourné.*/ };

28 Chapitre V - Héritage ou dérivation d'une classe28 Polygone_2D.cpp #include #include "Polygone_2D.h" Polygone_2D::Polygone_2D() { Nb_de_sommets = 0; } void Polygone_2D::Ajouter_sommet(int x, int y) { sommet_2D * P = new sommet_2D; (*P).x = x;(*P).y = y; Ensemble_des_sommets.Inserer_fin_liste(P); Nb_de_sommets = Nb_de_sommets + 1; }

29 Chapitre V - Héritage ou dérivation d'une classe29 Polygone_2D.cpp (suite) int Polygone_2D::Nombre_de_sommets() { return Nb_de_sommets; } void Polygone_2D::Detruire_Polygone_2D() { Ensemble_des_sommets.Detruire_liste(); Nb_de_sommets = 0; }

30 Chapitre V - Héritage ou dérivation d'une classe30 Polygone_2D.cpp (suite) float Polygone_2D::Aire_Triangle_2D(int x, int y, int u, int v, int a, int b) { float aire; aire = ((float) ((v - y)*(a - x) - (u - x)*(b-y))) / 2.0f; return aire; }

31 Chapitre V - Héritage ou dérivation d'une classe31 Polygone_2D.cpp (suite) float Polygone_2D::Aire_Polygone_2D() { int x, y, u, v, a, b; bool Fin; struct sommet_2D * P; float somme = 0.0; Ensemble_des_sommets.Positionner_debut_liste(); P = (sommet_2D *) Ensemble_des_sommets.Acces_element_courant(); x = (*P).x; y = (*P).y;

32 Chapitre V - Héritage ou dérivation d'une classe32 Polygone_2D.cpp (suite) Fin = Ensemble_des_sommets.Positionner_sommet_suivant(); P = (sommet_2D *) Ensemble_des_sommets.Acces_element_courant(); u = (*P).x; v = (*P).y; Fin = Ensemble_des_sommets.Positionner_sommet_suivant(); P = (sommet_2D *) Ensemble_des_sommets.Acces_element_courant(); a = (*P).x; b = (*P).y; somme = somme + Aire_Triangle_2D(x, y, u, v, a, b);

33 Chapitre V - Héritage ou dérivation d'une classe33 Polygone_2D.cpp (fin) while (Ensemble_des_sommets.Positionner_sommet_suivant() == false) { P = (sommet_2D *) Ensemble_des_sommets.Acces_element_courant(); u = a; v = b; a = (*P).x; b = (*P).y; somme = somme + Aire_Triangle_2D(x, y, u, v, a, b); } return somme; }

34 Chapitre V - Héritage ou dérivation d'une classe34 Application Polygone_2D.cpp #include #include "Polygone_2D.h" void main() { Polygone_2D Q; Q.Ajouter_sommet(1, 1);Q.Ajouter_sommet(1, 3); Q.Ajouter_sommet(2, 3);Q.Ajouter_sommet(2, 2); Q.Ajouter_sommet(3, 2);Q.Ajouter_sommet(3, 3); Q.Ajouter_sommet(4, 3);Q.Ajouter_sommet(4, 1); cout << "Nombre de sommets : " << Q.Nombre_de_sommets(); cout << "Aire du polygone 2D : " << Q.Aire_Polygone_2D(); Q.Detruire_Polygone_2D(); cout << "Nombre de sommets : " << Q.Nombre_de_sommets(); }

35 Chapitre V - Héritage ou dérivation d'une classe35 Héritage Exemple (suite) Liste_simple Polygone_2D Polygone_2D_convexe « hérite de » Exercices résolus (chap. IV)

36 Chapitre V - Héritage ou dérivation d'une classe36 Polygone_2D_convexe.h #include "Polygone_2D.h" class Polygone_2D_convexe : public Polygone_2D { /* Spécification fonctionnelle de la classe " Polygone_2D_convexe " dérivée de la classe "Polygone_2D". Composantes :Chaque composante est un sommet d'un polygone convexe Structure :Il existe une relation linéaire (structure) entre les sommets du polygone. Cette relation décrit le mode de parcours du contour polygonal dans le sens horaire.*/

37 Chapitre V - Héritage ou dérivation d'une classe37 Polygone_2D_convexe.h public: void Point_visible_Polygone_2D_convexe(float * x, float * y); /*Permet de calculer un point intérieur au polygone lequel est visible de tous ses sommets. Pré -Le polygone 2D convexe a déjà été créé et le nombre de sommets est supérieur ou égal à 3. Post -Les coordonnées réelles x, y d'un point visible du polygone 2D convexe sont retournées en paramètres. */ };

38 Chapitre V - Héritage ou dérivation d'une classe38 Polygone_2D_convexe.cpp #include #include "Polygone_2D_convexe.h" void Polygone_2D_convexe::Point_visible_Polygone_2D_convexe (float * x, float * y) { float Vx, Vy; struct sommet_2D * P; Ensemble_des_sommets.Positionner_debut_liste(); P = (sommet_2D *) Ensemble_des_sommets.Acces_element_courant(); Vx = (*P).x / (float) Nb_de_sommets; Vy = (*P).y / (float) Nb_de_sommets;

39 Chapitre V - Héritage ou dérivation d'une classe39 Polygone_2D_convexe.cpp while (Ensemble_des_sommets.Positionner_sommet_suivant() == false) { P = (sommet_2D *) Ensemble_des_sommets.Acces_element_courant(); Vx = Vx + (*P).x / (float) Nb_de_sommets; Vy = Vy + (*P).y / (float) Nb_de_sommets; } *x = Vx;*y = Vy; }

40 Chapitre V - Héritage ou dérivation d'une classe40 Application Polygone_2D_convexe.cpp #include #include "Polygone_2D_convexe.h" void main() { float a, b; Polygone_2D_convexe Q; Q.Ajouter_sommet(1, 1); Q.Ajouter_sommet(1, 3); Q.Ajouter_sommet(4, 3); Q.Ajouter_sommet(4, 1);

41 Chapitre V - Héritage ou dérivation d'une classe41 Application Polygone_2D_convexe.cpp cout << "Nombre de sommets : " << Q.Nombre_de_sommets(); cout << "Aire du polygone 2D : " << Q.Aire_Polygone_2D(); Q.Point_visible_Polygone_2D_convexe(&a, &b); cout << "Point visible : " << a << ", " << b; Q.Detruire_Polygone_2D(); cout << "Nombre de sommets : " << Q.Nombre_de_sommets(); }

42 Chapitre V - Héritage ou dérivation d'une classe42 Héritage et protection des membres Rappel:  3 étiquettes de protection : public, private et protected. Une classe dérivée peut accéder aux données membres publiques et protégées de la classe de base. Les données privées ne sont manipulables que par les fonctions membres public et protected de la classe qui les a définies. Principe : Mieux vaut laisser privées toutes les données car, - n’importe quelle fonction membre de classe dérivée peut corrompre les données protégées de la classe de base. - les classes possédant des données membres protégées sont difficiles à modifier car quelqu’un peut avoir écrit une classe dérivée dont le code repose sur ces données membres protégées.

43 Chapitre V - Héritage ou dérivation d'une classe43 Héritage et protection des membres Exemple: class A { public: int i; protected: int j; private: int z; public: A(); void Affiche(); }; class B : public A { public : void Utilise(); }; A::A() { i=1; j=2; z=3; }

44 Chapitre V - Héritage ou dérivation d'une classe44 Héritage et protection des membres Exemple:(suite) void A::Affiche() { cout << "i : " << i << " \n "; cout << "j : " << j << " \n "; cout << "z : " << z << " \n "; } void B:: Utilise() { i=4; j=5; // z=6;// impossible, car z est privée. Affiche(); } void main() { B b; b.Utilise(); // b.i = 7;// possible, car i est // public. // b.Affiche();// possible. } i : 4 j : 5 z : 3 public

45 Chapitre V - Héritage ou dérivation d'une classe45 Héritage et protection des membres Note: La donnée membre i et la fonction Affiche() sont accessibles par toute fonction qui déclare un objet de ce type ou d ’un type dérivé. Quelles que soient les étiquettes de protection, une fonction membre d’une classe peut accéder à toutes les données membres de cette classe. Un constructeur, comme toute fonction membre, doit être intégré à une étiquette de protection. Dans la plupart des cas, les constructeurs sont déclarés dans la section public, ce qui permet à quiconque de créer les objets de cette classe en utilisant ces constructeurs.

46 Chapitre V - Héritage ou dérivation d'une classe46 Spécification de l’héritage En dérivant une classe, nous devons indiquer l ’étiquette de protection: class B : public A// Autres choix : private et protected { ….. }; Permet de spécifier la façon dont se propagera l’héritage en termes d ’accès dans une hiérarchie de classes. Dans la pratique, vous utiliserez presque exclusivement l’étiquette public. 2 règles d ’utilisation: Si vous omettez d ’employer un de ces mots clés, l’étiquette private est la valeur par défaut. Le choix de l’étiquette ne change rien pour la classe dérivée (B dans l’exemple) La spécification d’héritage n ’interviendra que pour les classes dérivées de B.

47 47 Spécification de l’héritage Nous pouvons donc préciser pour une classe, la politique d’accès de ses propres classes dérivées. Si B dérive de A avec le mot clé: public: La protection des membres de la classe A reste inchangée au niveau de B. On peut imaginer chaque objet de la classe dérivée comme un objet de la classe de base. protected: Les membres public et protected de A sont considérés comme protected dans la classe B. Dans ce cas, les classes dérivées de B ont toujours accès aux membres de A. private: Les membres public et protected de A sont considérés comme private dans la classe B. Les fonctions deviennent des utilitaires. Les classes dérivées de B n’ont plus accès aux membres de A. Forme alternative de la composition (voir ultérieurement).

48 48 Sommaire de l’accessibilité des membres de la classe de base dans une classe dérivée Mode d’accès aux membres de la classe de base Héritage public Héritage protectedHéritage private public public dans la classe dérivée. Accessible directement à partir de toute fonction membre, friend ou non membre. protected dans la classe dérivée. Accessible directement à partir de toute fonc- tion membre ou friend. private dans la classe dérivée. Accessible directe- ment à partir de toute fonction membre ou friend. protected protected dans la classe dérivée. Accessible directement à partir de toute fonction membre ou friend. protected dans la classe dérivée. Accessible directement à partir de toute fonc- tion membre ou friend. private dans la classe dérivée. Accessible directe- ment à partir de toute fonction membre ou friend.

49 49 Sommaire de l’accessibilité des membres de la classe de base dans une classe dérivée Mode d’accès aux membres de la classe de base Héritage public Héritage protectedHéritage private private masqué dans la classe dérivée. Accessible directement à partir de toute fonction membre ou friend par le biais des fonctions membres public ou protected de la classe de base. masqué dans la classe dérivée. Accessible directement à partir de toute fonc- tion membre ou friend par le biais des fonctions membres public ou protected de la classe de base. masqué dans la classe dérivée. Accessible directe- ment à partir de toute fonction membre ou friend par le biais des fonctions membres public ou protected de la classe de base.

50 Chapitre V - Héritage ou dérivation d'une classe50 Spécification de l’héritage L’étiquette de protection private utilisée par la classe de base ne peut pas être modifiée par les classes dérivées. Par l’héritage, vous ne pouvez qu’augmenter le niveau de sécurité, jamais le diminuer. Dans la pratique, les 2 spécifications d’héritage protected et private sont rarement utilisées puisqu’elles ont tendance à couper la relation d’héritage.

51 Chapitre V - Héritage ou dérivation d'une classe51 Spécification de l ’héritage Exemple: class A { public: int i; protected: int j; private: int z; }; class B : private A { // B a accès à A::i et A::j }; class C : public B { // C n’a pas accès aux données de A. }; class D : protected A { // D a accès à A::i et A::j }; class E : public D { // E a accès à A::i et A::j }; void main() { E e;// e.i n’est pas accessible. }

52 Chapitre V - Héritage ou dérivation d'une classe52 Héritage, constructeurs et destructeurs L’héritage entraîne la création d ’objets en cascade. Ex.:Si B dérive de A, la création d’un objet de type B entraîne automatiquement la création d’un objet de type A. La création d ’un objet se traduit par l ’appel au constructeur de cette classe. Qu’est-ce qui se passera au niveau des constructeurs des classes impliquées dans une relation d’héritage? Le constructeur d’une classe dérivée va obligatoirement appeler le constructeur de sa classe de base. La destruction des objets liés par une relation d’héritage passe également par un enchaînement d’appels aux destructeurs des classes impliquées.

53 Chapitre V - Héritage ou dérivation d'une classe53 Héritage, constructeurs et destructeurs Exemple:les classes Polygone_2D et Polygone_2D_convexe Polygone_2D_convexe est une classe sans constructeur ou, plus précisément, avec un constructeur par défaut utilisé lors de la création des objets dérivés. Le constructeur de la classe Polygone_2D était donc appelé automatiquement. Chaque fois que vous créez un objet, s’il s’agit d’une classe dérivée, le constructeur va en premier lieu appeler le constructeur de la classe de base. Les objets de base sont créés avant les objets dérivés. Pour les destructeurs, c’est l’ordre inverse qui est employé: le destructeur d’une classe dérivée est appelé avant celui de sa classe de base.

54 Chapitre V - Héritage ou dérivation d'une classe54 Héritage, constructeurs et destructeurs Supposons que nous créions un objet d’une classe dérivée où la classe de base et la classe dérivée contiennent toutes deux des objets d’autres classes. Lorsqu’un objet de cette classe dérivée est créé, le constructeur des objets membres de la classe de base s’exécute en premier, suivi du constructeur des objets membres de la classe dérivée, puis du constructeur de la classe dérivée. Les destructeurs sont appelés dans l’ordre inverse de celui des constructeurs.

55 Chapitre V - Héritage ou dérivation d'une classe55 Héritage Exemple Liste_simple Polygone_2D Polygone_2D_convexe « hérite de » Exercices résolus (chap. IV) Triangle_2D « hérite de »

56 Chapitre V - Héritage ou dérivation d'une classe56 Héritage« Polygone_2D.h » #include "Liste_simple.h" enum type_de_polygone {quelconque, convexe, triangle, quadrilatere}; struct sommet_2D { int x, y; }; class Polygone_2D {... protected: int Nb_de_sommets;/* Nombre de sommets du polyg.*/ type_de_polygone statut; Liste_simple Ensemble_des_sommets; …

57 Chapitre V - Héritage ou dérivation d'une classe57 Héritage« Polygone_2D.h » public: Polygone_2D(); /*Permet de créer un polygone 2D quelconque à 0 sommet. Pré -Nil. Post -Un polygone quelconque à 0 sommet est créé.*/ type_de_polygone Acces_statut(); /*Retourne le type de polygone créé. Pré -Le polygone 2D a déjà été créé. Post -Le type de polygone est retourné.*/...

58 Chapitre V - Héritage ou dérivation d'une classe58 Héritage « Polygone_2D.cpp » #include #include "Polygone_2D.h" Polygone_2D::Polygone_2D() { Nb_de_sommets = 0; statut = quelconque; } type_de_polygone Polygone_2D::Acces_statut() { return statut; }

59 Chapitre V - Héritage ou dérivation d'une classe59 Héritage « Polygone_2D_convexe.h » #include "Polygone_2D.h" class Polygone_2D_convexe : public Polygone_2D {... public: Polygone_2D_convexe(); /*Permet de créer un polygone 2D convexe à 0 sommet. Pré -Nil. Post -Un polygone convexe à 0 sommet est créé.*/...

60 Chapitre V - Héritage ou dérivation d'une classe60 Héritage « Polygone_2D_convexe.cpp » #include "Polygone_2D_convexe.h" Polygone_2D_convexe::Polygone_2D_convexe() { Nb_de_sommets = 0; // pas nécessaire statut = convexe; }

61 Chapitre V - Héritage ou dérivation d'une classe61 Héritage« Triangle_2D.h » #include "Polygone_2D_convexe.h" class Triangle_2D : public Polygone_2D_convexe { /*Spécification fonctionnelle de la classe " Triangle_2D " dérivée de la classe "Polygone_2D_convexe". Composantes :Chaque composante est un sommet d'un triangle 2D. Structure :Il existe une relation linéaire (structure) entre les sommets du polygone. Cette relation décrit le mode de parcours du contour polygonal dans le sens horaire.*/

62 Chapitre V - Héritage ou dérivation d'une classe62 Héritage« Triangle_2D.h » public: Triangle_2D(); /*Permet de créer un triangle 2D à 0 sommet. Pré -Nil. Post -Un triangle à 0 sommet est créé.*/ };

63 Chapitre V - Héritage ou dérivation d'une classe63 Héritage« Triangle_2D.cpp » #include "Triangle_2D.h" Triangle_2D::Triangle_2D() { Nb_de_sommets = 0;// inutile. statut = triangle; }

64 Chapitre V - Héritage ou dérivation d'une classe64 Héritage «Application Triangle_2D.cp p » #include #include "Triangle_2D.h" void main() { float a, b; Triangle_2D Q; Q.Ajouter_sommet(1, 1); Q.Ajouter_sommet(1, 3); Q.Ajouter_sommet(4, 3); if (Q.Acces_statut() == triangle) cout << " Ceci est un triangle.";

65 Chapitre V - Héritage ou dérivation d'une classe65 Héritage «Application Triangle_2D.cpp » cout << "Nombre de sommets : " << Q.Nombre_de_sommets(); cout << "Aire du triangle 2D : " << Q.Aire_Polygone_2D(); Q.Point_visible_Polygone_2D_convexe(&a, &b); cout << "Point visible : " << a << ", " << b; Q.Detruire_Polygone_2D(); cout << "Nombre de sommets : " << Q.Nombre_de_sommets(); } FIN

66 Chapitre V - Héritage ou dérivation d'une classe66 Dériver une classe qui possède un constructeur avec arguments Contrainte : Le constructeur de la classe dérivée appelle automatiquement celui de la classe de base uniquement si les 2 classes impliquées possèdent un constructeur sans argument. Autrement, nous devons appeler le constructeur de la classe de base. Comment : Il faut définir un constructeur dans la classe dérivée pour appeler le constructeur de la classe de base et lui passer les arguments adéquats. En plus des données nécessaires au constructeur de la classe de base, nous pouvons ajouter, le cas échéant, des arguments supplémentaires à votre constructeur pour les besoins internes de votre classe.

67 Chapitre V - Héritage ou dérivation d'une classe67 Exemple class Aire_de_stationnement { protected: int Nb_places;/* Capacité maximale*/ int Nb_places_disponibles; public: Aire_de_stationnement(int Capacite); /*Permet de créer une aire de stationnement dont la capacité est fixée en paramètre. Pré -Nil. Post -Une aire de stationnement vide est créée.*/

68 Chapitre V - Héritage ou dérivation d'une classe68 Exemple (suite) void Arrivee_voiture(); /*Simule l'arrivée d'une nouvelle voiture dans le stationnement. Pré -L'aire de stationnement est créée et des places sont disponibles. Post -Une place de moins est disponible.*/ void Depart_voiture(); /*Simule le départ d'une voiture du stationnement. Pré -L'aire de stationnement est créée et n'est pas vide. Post -Une place de plus est disponible.*/

69 Chapitre V - Héritage ou dérivation d'une classe69 Exemple (suite) bool Capacite_maximum_atteinte(); /*Vérifie s'il existe des places disponibles. Pré -L'aire de stationnement est créée. Post -Retourne true si aucune place n'est disponible. False autrement.*/ }; class Stationnement_pour_handicapes : public Aire_de_stationnement { public: Stationnement_pour_handicapes(); };

70 Chapitre V - Héritage ou dérivation d'une classe70 Exemple (suite) #include "Stationnement.h" Aire_de_stationnement::Aire_de_stationnement(int Capacite) { Nb_places = Capacite; Nb_places_disponibles = Capacite; } void Aire_de_stationnement::Arrivee_voiture() { Nb_places_disponibles = Nb_places_disponibles - 1; }

71 Chapitre V - Héritage ou dérivation d'une classe71 Exemple (suite) void Aire_de_stationnement::Depart_voiture() { Nb_places_disponibles = Nb_places_disponibles + 1; } bool Aire_de_stationnement::Capacite_maximum_atteinte() { if (Nb_places_disponibles == 0) return true; else return false; }

72 Chapitre V - Héritage ou dérivation d'une classe72 Exemple (suite) Stationnement_pour_handicapes::Stationnement_pour_handicapes() : Aire_de_stationnement(3) { } Le constructeur de la classe dérivée peut évoluer. Syntaxe d’appel au constructeur de base La syntaxe d’appel au constructeur de base montre bien la réalité de l’ordre d’appel aux constructeurs.

73 Chapitre V - Héritage ou dérivation d'une classe73 Exemple (suite) #include #include "Stationnement.h" void main() { Stationnement_pour_handicapes S; S.Arrivee_voiture();S.Arrivee_voiture();S.Arrivee_voiture(); if (S.Capacite_maximum_atteinte() == true) cout << " Capacite maximale atteinte "; S.Depart_voiture(); if (S.Capacite_maximum_atteinte() == false) cout << " Capacite maximale non atteinte "; }

74 Chapitre V - Héritage ou dérivation d'une classe74 Ordre d’appel des constructeurs et destructeurs #include typedef enum {insecte = 0, vent, animal, eau, humain} mode_de_pollinisation; typedef enum {guepe, coccinelle, mouche, libellule, cigale, abeille, fourmi, sauterelle, patineur} type_insecte; class Pollinisation { protected :mode_de_pollinisation Mode; public :Pollinisation(mode_de_pollinisation M); ~Pollinisation(); };

75 Chapitre V - Héritage ou dérivation d'une classe75 Ordre d’appel des constructeurs et destructeurs Pollinisation::Pollinisation(mode_de_pollinisation M) { Mode = M; cout<< "Constructeur de Pollinisation: " << Mode << endl; } Pollinisation::~Pollinisation() { cout<< "Destructeur de Pollinisation: " << Mode << endl; }

76 Chapitre V - Héritage ou dérivation d'une classe76 Ordre d’appel des constructeurs et destructeurs class Pollinisation_par_insecte : public Pollinisation { private :type_insecte Nom_d_insecte; public :Pollinisation_par_insecte(type_insecte Nom); ~Pollinisation_par_insecte(); }; Pollinisation_par_insecte::Pollinisation_par_insecte(type_insecte Nom) :Pollinisation(insecte) { Nom_d_insecte = Nom; cout<< "Constructeur de Pollinisation par insecte: " << Mode << " " << Nom_d_insecte << endl; }

77 77 Ordre d’appel des constructeurs et destructeurs Pollinisation_par_insecte::~Pollinisation_par_insecte() { cout<< "Destructeur de Pollinisation par insecte : " << Mode << " " << Nom_d_insecte << endl; } void main() { Pollinisation P(vent); { Pollinisation Q(eau); } Pollinisation_par_insecte R(guepe); Pollinisation_par_insecte S(abeille); }

78 78 Ordre d’appel des constructeurs et destructeurs SORTIE Constructeur de Pollinisation: 1 Constructeur de Pollinisation: 3 Destructeur de Pollinisation: 3 Constructeur de Pollinisation: 0 Constructeur de Pollinisation par insecte: 0 0 Constructeur de Pollinisation: 0 Constructeur de Pollinisation par insecte: 0 5 Destructeur de Pollinisation par insecte: 0 5 Destructeur de Pollinisation: 0 Destructeur de Pollinisation par insecte: 0 0 Destructeur de Pollinisation: 0 Destructeur de Pollinisation: 1

79 Chapitre V - Héritage ou dérivation d'une classe79 Héritage multiple C++ permet de définir une classe qui dérive de 2 ou plusieurs classes. Cette technique offre la possibilité de factoriser des attributs et des comportements provenant de classes qui ont peu ou pas de points communs. Exemple :La classe C dérive à la fois des classes A et B. class C : public A, public B { }; La création d’un objet de type C entraîne la création d’un objet de type A et un objet de type B. Le constructeur de la classe C doit appeler les 2 constructeurs des classes de base (A et B). L’héritage multiple est peu utilisée (voir plus loin d’autres techniques).

80 Chapitre V - Héritage ou dérivation d'une classe80 Exemple Liste_simple Polygone_2D Polygone_2D_convexe « hérite de » Triangle_2D « hérite de » Caracteristiques_physiques Objet_2D « hérite de »

81 Chapitre V - Héritage ou dérivation d'une classe81 Classe « Caracteristiques_physiques » class Caracteristiques_physiques { protected: int couleur_remplissage; int couleur_contour; public: void Init_couleur_remplissage(int C); /*Permet d'initialiser la couleur de remplissage C. Pré -Nil. Post -La couleur de remplissage est C.*/

82 Chapitre V - Héritage ou dérivation d'une classe82 Classe « Caracteristiques_physiques » void Init_couleur_contour(int C); /*Permet d'initialiser la couleur de contour C. Pré -Nil. Post -La couleur de contour est C.*/ int Donner_couleur_remplissage(); /*Retourne la couleur de remplissage. Pré -La couleur de remplissage est initialisée. Post -La couleur de remplissage est retournée.*/ int Donner_couleur_contour(); /*Retourne la couleur de contour. Pré -La couleur de contour est initialisée. Post -La couleur de contour est retournée.*/ };

83 Chapitre V - Héritage ou dérivation d'une classe83 Classe « Caracteristiques_physiques » #include "Caracteristiques_physiques.h" void Caracteristiques_physiques::Init_couleur_remplissage(int C) { couleur_remplissage = C; } void Caracteristiques_physiques::Init_couleur_contour(int C) { couleur_contour = C; }

84 Chapitre V - Héritage ou dérivation d'une classe84 Classe « Caracteristiques_physiques » int Caracteristiques_physiques::Donner_couleur_remplissage() { return couleur_remplissage; } int Caracteristiques_physiques::Donner_couleur_contour() { return couleur_contour; }

85 Chapitre V - Héritage ou dérivation d'une classe85 Classe « Objet_2D » #include "Polygone_2D.h" #include "Caracteristiques_physiques.h" class Objet_2D:public Polygone_2D, public Caracteristiques_physiques { protected: int repere_x; int repere_y; public: Objet_2D(int x, int y); /*Permet de créer un objet 2D avec un repère x, y. Pré -Nil. Post -Un objet 2D est créé.*/

86 Chapitre V - Héritage ou dérivation d'une classe86 Classe « Objet_2D » void Modifier_repere(int x, int y); /*Permet de modifier le repère de l'objet 2D. Pré -L'objet 2D a été créé. Post -Le repère de l'objet est maintenant x, y.*/ void Donner_repere(int * x, int * y); /*Retourne en paramètre le repère de l'objet. Pré -L'objet 2D a été créé. Post -Le repère de l'objet est retourné.*/ };

87 Chapitre V - Héritage ou dérivation d'une classe87 Classe « Objet_2D » #include "Objet_2D.h" Objet_2D::Objet_2D(int x, int y) : Polygone_2D(), Caracteristiques_physiques() { repere_x = x;repere_y = y; } void Objet_2D::Modifier_repere(int x, int y) { repere_x = x;repere_y = y; } void Objet_2D::Donner_repere(int * x, int * y) { *x = repere_x;*y = repere_y; }

88 Chapitre V - Héritage ou dérivation d'une classe88 Classe « Application Objet_2D » #include #include "Objet_2D.h" void main() { int x, y; Objet_2D Q(1,2); Q.Ajouter_sommet(1, 1);Q.Ajouter_sommet(1, 3); Q.Ajouter_sommet(2, 3);Q.Ajouter_sommet(2, 2); Q.Ajouter_sommet(3, 2);Q.Ajouter_sommet(3, 3); Q.Ajouter_sommet(4, 3);Q.Ajouter_sommet(4, 1); Q.Init_couleur_remplissage(2); Q.Init_couleur_contour(3);

89 Chapitre V - Héritage ou dérivation d'une classe89 Classe « Application Objet_2D » cout << "Nombre de sommets : " << Q.Nombre_de_sommets(); cout << "Aire du polygone 2D : " << Q.Aire_Polygone_2D(); cout << "Couleur de remplissage : " <

90 Chapitre V - Héritage ou dérivation d'une classe90 Héritage multiple Une autre approche à privilégier pour définir la classe Objet_2D passe par le concept de classe interne.

91 Chapitre V - Héritage ou dérivation d'une classe91 Multiples inclusions d’un fichier en-tête Pour empêcher de multiples inclusions d’un fichier en-tête, la déclaration d’une classe doit être comprise dans le code de précompilation suivant : #ifndef Client_h #define Client_h ….. #endif Cela empêche l’inclusion du code situé entre #ifndef et #endif si le nom Client_h est déjà défini. Le nom de la constante symbolique est défini par convention.

92 Chapitre V - Héritage ou dérivation d'une classe92 Classes virtuelles Utilisées dans le cas de l’héritage multiple afin de permettre à plusieurs classes de partager le même objet de base. A BC D class A { }; class B : public A { }; class C : public A { }; class D : public B, public C { };

93 Chapitre V - Héritage ou dérivation d'une classe93 Classes virtuelles Création d ’un objet de type D: B, AC, AD car B dérive de A, C dérive de A. 2 objets de type A sont créés. Cela peut provoquer des erreurs si l’on tente d’accéder aux membres de A. Pour compenser un mauvais diagramme de classe, on peut faire en sorte que la classe A soit une classe virtuelle. Ainsi, il n’existera alors qu’un seul objet de type A pour chaque objet de type D.

94 Chapitre V - Héritage ou dérivation d'une classe94 Classes virtuelles class A { }; class B : virtual public A { }; class C : virtual public A { }; class D : public B, public C { }; Peu d’intérêt dans la mesure où elles ne servent généralement qu’à compenser la déficience d’une hiérarchie de classes. éviter ce style d’architecture

95 Chapitre V - Héritage ou dérivation d'une classe95 Conclusion Les utilisateurs n’ont pas besoin de voir le code source des classes à partir desquelles ils héritent. La création d’une classe dérivée n’affecte en rien le code source de sa classe de base; l’intégrité d’une classe de base est préservée par l’héritage. Des modifications apportées à une classe de base n’impliquent pas de changement au niveau des classes dérivées aussi longtemps que les interfaces public et protected de la classe de base demeurent inchangées. Toutefois, les classes dérivées peuvent nécessiter une nouvelle compilation. FIN


Télécharger ppt "Chapitre V Héritage ou dérivation d’une classe. 2 Héritage Permet de créer une classe à partir d’une autrei.e.la nouvelle classe bénéficie des données."

Présentations similaires


Annonces Google