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

Héritage ou dérivation d’une classe

Présentations similaires


Présentation au sujet: "Héritage ou dérivation d’une classe"— Transcription de la présentation:

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

2 Avantages de l’héritage :
Permet de créer une classe à partir d’une autre i.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. Avantages de l’héritage : 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.

3 Avantages de l’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 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 Réutilisation par « recyclage »
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. Souvent plus facile de tout réécrire… 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.

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. Mythes de la réutilisation Ne demande pas de changement pour être utilisé dans un nouveau programme. 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 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 Illustration du concept d’héritage
Citoyen Commerçant Fournisseur de bois

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

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

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

12 Types d’héritage (Yves Roy)
Spécialisation 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. Spécification Construction Généralisation Extension Figure géométrique Limitation Codes communs Opérations imposées aux figures géométriques : Afficher - Aire - Normale - etc. Polygone Cercle

13 Types d’héritage (Yves Roy)
Spécialisation 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. Spécification Construction Généralisation Extension Liste simple Limitation 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 Pile

14 Types d’héritage (Yves Roy)
Spécialisation 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. Spécification Construction Généralisation Extension Limitation Codes communs

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

16 Types d’héritage (Yves Roy)
Spécialisation 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. Spécification Construction Généralisation Extension Dèque Limitation 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 Pile Chapitre V - Héritage ou dérivation d'une classe

17 Types d’héritage (Yves Roy)
Spécialisation 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. Spécification Construction Généralisation Extension Limitation Codes communs Chapitre V - Héritage ou dérivation d'une classe

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

19 Chapitre V - Héritage ou dérivation d'une classe
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. Chapitre V - Héritage ou dérivation d'une classe

20 Chapitre V - Héritage ou dérivation d'une classe
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 : <acces> Nom_de_la_classe_de_base { ….. }; <acces> désigne l ’une des 3 valeurs suivantes: public, private et protected. à venir Chapitre V - Héritage ou dérivation d'une classe

21 Chapitre V - Héritage ou dérivation d'une classe
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. Chapitre V - Héritage ou dérivation d'une classe

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

23 Chapitre V - Héritage ou dérivation d'une classe
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. */ Chapitre V - Héritage ou dérivation d'une classe

24 Chapitre V - Héritage ou dérivation d'une classe
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. */ Chapitre V - Héritage ou dérivation d'une classe

25 Chapitre V - Héritage ou dérivation d'une classe
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.*/ Chapitre V - Héritage ou dérivation d'une classe

26 Chapitre V - Héritage ou dérivation d'une classe
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. */ Chapitre V - Héritage ou dérivation d'une classe

27 Chapitre V - Héritage ou dérivation d'une classe
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é. */ }; Chapitre V - Héritage ou dérivation d'une classe

28 Chapitre V - Héritage ou dérivation d'une classe
Polygone_2D.cpp #include <iostream.h> #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; Chapitre V - Héritage ou dérivation d'une classe

29 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; Chapitre V - Héritage ou dérivation d'une classe

30 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; } Chapitre V - Héritage ou dérivation d'une classe

31 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; Chapitre V - Héritage ou dérivation d'une classe

32 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; a = (*P).x; b = (*P).y; somme = somme + Aire_Triangle_2D(x, y, u, v, a, b); Chapitre V - Héritage ou dérivation d'une classe

33 Chapitre V - Héritage ou dérivation d'une classe
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; Chapitre V - Héritage ou dérivation d'une classe

34 Application Polygone_2D.cpp
#include <iostream.h> #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(); } Chapitre V - Héritage ou dérivation d'une classe

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

36 Chapitre V - Héritage ou dérivation d'une classe
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. */ Chapitre V - Héritage ou dérivation d'une classe

37 Chapitre V - Héritage ou dérivation d'une classe
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. */ }; Chapitre V - Héritage ou dérivation d'une classe

38 Chapitre V - Héritage ou dérivation d'une classe
Polygone_2D_convexe.cpp #include <iostream.h> #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; Chapitre V - Héritage ou dérivation d'une classe

39 Chapitre V - Héritage ou dérivation d'une classe
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; Chapitre V - Héritage ou dérivation d'une classe

40 Application Polygone_2D_convexe.cpp
#include <iostream.h> #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); Chapitre V - Héritage ou dérivation d'une classe

41 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(); } Chapitre V - Héritage ou dérivation d'une classe

42 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. Chapitre V - Héritage ou dérivation d'une classe

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

44 Héritage et protection des membres
Exemple: (suite) void main() { B b; b.Utilise(); // b.i = 7;// possible, car i est // public. // b.Affiche(); // possible. } 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(); i : 4 j : 5 z : 3 public Chapitre V - Héritage ou dérivation d'une classe

45 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. Chapitre V - Héritage ou dérivation d'une classe

46 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. Chapitre V - Héritage ou dérivation d'une classe

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é: 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. public: 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 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 protected Héritage private 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. public 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. protected

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 protected Héritage 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. private

50 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. Chapitre V - Héritage ou dérivation d'une classe

51 Spécification de l ’héritage
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. } 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 Chapitre V - Héritage ou dérivation d'une classe

52 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. Chapitre V - Héritage ou dérivation d'une classe

53 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. Chapitre V - Héritage ou dérivation d'une classe

54 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. Chapitre V - Héritage ou dérivation d'une classe

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

56 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; Chapitre V - Héritage ou dérivation d'une classe

57 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é. */ ... Chapitre V - Héritage ou dérivation d'une classe

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

59 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éé. */ Chapitre V - Héritage ou dérivation d'une classe

60 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; } Chapitre V - Héritage ou dérivation d'une classe

61 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. */ Chapitre V - Héritage ou dérivation d'une classe

62 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éé. */ }; Chapitre V - Héritage ou dérivation d'une classe

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

64 Héritage «Application Triangle_2D.cpp »
#include <iostream.h> #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."; Chapitre V - Héritage ou dérivation d'une classe

65 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(); } FIN Chapitre V - Héritage ou dérivation d'une classe

66 Dériver une classe qui possède un constructeur avec arguments
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. Contrainte : 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. Comment : Chapitre V - Héritage ou dérivation d'une classe

67 Chapitre V - Héritage ou dérivation d'une classe
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. */ Chapitre V - Héritage ou dérivation d'une classe

68 Chapitre V - Héritage ou dérivation d'une classe
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. */ Chapitre V - Héritage ou dérivation d'une classe

69 Chapitre V - Héritage ou dérivation d'une classe
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(); Chapitre V - Héritage ou dérivation d'une classe

70 Chapitre V - Héritage ou dérivation d'une classe
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; Chapitre V - Héritage ou dérivation d'une classe

71 Chapitre V - Héritage ou dérivation d'une classe
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; Chapitre V - Héritage ou dérivation d'une classe

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

73 Chapitre V - Héritage ou dérivation d'une classe
Exemple (suite) #include <iostream.h> #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 "; } Chapitre V - Héritage ou dérivation d'une classe

74 Ordre d’appel des constructeurs et destructeurs
#include <iostream.h> 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(); }; Chapitre V - Héritage ou dérivation d'une classe

75 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: " Chapitre V - Héritage ou dérivation d'une classe

76 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; } Chapitre V - Héritage ou dérivation d'une classe

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 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 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: 1

79 Chapitre V - Héritage ou dérivation d'une classe
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). Chapitre V - Héritage ou dérivation d'une classe

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

81 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. */ Chapitre V - Héritage ou dérivation d'une classe

82 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. */ }; Chapitre V - Héritage ou dérivation d'une classe

83 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; Chapitre V - Héritage ou dérivation d'une classe

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

85 Chapitre V - Héritage ou dérivation d'une classe
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éé. */ Chapitre V - Héritage ou dérivation d'une classe

86 Chapitre V - Héritage ou dérivation d'une classe
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. Post - Le repère de l'objet est retourné. */ }; Chapitre V - Héritage ou dérivation d'une classe

87 Chapitre V - Héritage ou dérivation d'une classe
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) void Objet_2D::Donner_repere(int * x, int * y) *x = repere_x; *y = repere_y; Chapitre V - Héritage ou dérivation d'une classe

88 Classe « Application Objet_2D »
#include <iostream.h> #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); Chapitre V - Héritage ou dérivation d'une classe

89 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 : " <<Q.Donner_couleur_remplissage(); cout << "Couleur de contour : " << Q.Donner_couleur_contour(); Q.Donner_repere(&x, &y); cout << "Repere : " << x << " " << y; Q.Detruire_Polygone_2D(); } Chapitre V - Héritage ou dérivation d'une classe

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

91 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. Chapitre V - Héritage ou dérivation d'une classe

92 Chapitre V - Héritage ou dérivation d'une classe
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. class A { }; class B : public A class C : public A class D : public B, public C A B C D Chapitre V - Héritage ou dérivation d'une classe

93 Chapitre V - Héritage ou dérivation d'une classe
Classes virtuelles Création d ’un objet de type D: B, A C, A D 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. Chapitre V - Héritage ou dérivation d'une classe

94 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 Chapitre V - Héritage ou dérivation d'une classe

95 Chapitre V - Héritage ou dérivation d'une classe
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 Chapitre V - Héritage ou dérivation d'une classe


Télécharger ppt "Héritage ou dérivation d’une classe"

Présentations similaires


Annonces Google