Héritage ou dérivation d’une classe

Slides:



Advertisements
Présentations similaires
Systèmes en temps réel Héritage avec les capsules.
Advertisements

Programmation Orientée Objet (POO)
Leçon 3 : Héritage IUP 2 Génie Informatique
Introduction à la POO: Les classes vs les objets
بسم الله الرحمن الرحيم. Institut Supérieure des Etudes Technologiques de Kébili.
Cours 7 - Les pointeurs, l'allocation dynamique, les listes chaînées
Programmation orientée objet
Principes de la technologie orientée objets
Algorithmique et Programmation
Leçon 6 : Structures de données dynamiques IUP 2 Génie Informatique Méthode et Outils pour la Programmation Françoise Greffier.
Bibliothèque standard du C++
IFT1025, Programmation 2 Jian-Yun Nie
Introduction au paradigme objet Concepts importants surcharge (overload) redéfinition (override) Définition d’une classe Définition des attributs.
C++ : classes Introduction aux Langages Orientés Objets
Classes abstraites et Interfaces
Master 1 SIGLIS Java Lecteur Stéphane Tallard Chapitre 5 – Héritage, Interfaces et Listes génériques.
Test et débogage Tests unitaires. Gestion d’erreurs. Notion d’état, de pré-condition et de post-condition. Assertion. Traces de programme. Débogueur et.
Structures de données IFT-2000
Structures de données IFT-10541
Programme de baccalauréat en informatique Programmation Orientée Objets IFT Thierry EUDE Module 7 : Classes et fonctions paramétrables Département.
Les Fonctions. Définir une fonction Sections de code indépendantes que lon peut appeler à nimporte quel moment et dans nimporte quel ordre. Bout de code.
Introduction au paradigme orienté-objet (suite)
1 PROTOTYPE PGC++ Vecteur_3D DÉFINITION. 2 class Vecteur_3D { private : float vx, vy, vz, vw; // Représentation en coordonnées homogènes. public : Vecteur_3D();
P. Van Roy, LINF1251 LINF1251: Le Langage Java Peter Van Roy Département dIngénierie Informatique, UCL
1 IFT 6800 Atelier en Technologies dinformation Le langage de programmation Java chapitre 3 : Classes et Objects.
Types de données abstrait et mécanismes d'encapsulation
COURS DE PROGRAMMATION ORIENTEE OBJET :
Leçon 1 : notion dobjet IUP Génie Informatique Besançon Méthode et Outils pour la Programmation Françoise Greffier Université de Franche-Comté.
Texture 2D en PGC++.
99 Réutilisation du code grâce à l'héritage. 9-2 Objectifs À la fin de ce cours, vous serez capables de : Définir l'héritage Utiliser l'héritage pour.
INF1101 Algorithmes et structures de données
Structures de données IFT-2000 Abder Alikacem L’héritage en C++ Département d’informatique et de génie logiciel Édition Septembre 2009.
Classes et objets Types de données abstraits, programmation orientée objet, classes, objets,
Procédures et fonctions
Patrons de conceptions de créations
Héritage Licence Informatique Besançon Méthode et Outils pour la Programmation Françoise Greffier.
Introduction à la programmation orientée objets
Héritage et composition
RAPPEL Qu’est ce qu’une structure de contrôle itérative ?
(Vient du grec et signifie « Peut prendre plusieurs formes »)
Travaux Pratiques Représentation des connaissances
LIFI-Java 2004 Séance du Mercredi 22 sept. Cours 3.
La notion de type revisitée en POO
Les principes de la modélisation de systèmes
Héritage multiple En langage C++, il est possible d’utiliser l’héritage multiple. Il permet de créer des classes dérivées à partir de plusieurs classes.
GESTION ET TRAITEMENT DES ERREURS
La Modélisation Orientée Objet Concevoir un programme : modélisation du problème à résoudre Notion de programme : machine de Turing Pouvoir d’expression.
11/04/ L'héritage Cours 7 Cours 7.
Algorithmique et programmation (1)‏
Programmation objet La base.
Designs Patterns comment rendre son code faiblement couplé, et maintenable...
7ième Classe (Mardi, 24 novembre) CSI2572. Devoir 3 ?
Variables et accès en Java. Déclaration des variables final transient static private Printer hp; transient => ne doivent pas être sérialisées volatile.
Introduction à la programmation objet en C++
5ième Classe (Mercredi, 19 octobre) Prog CSI2572.
C++ L’HERITAGE Fayçal BRAÏKI DUT INFORMATIQUE.
Chapitre III Introduction aux objets et aux classes.
Les classes Introduction aux Langages Orientés Objets
La programmation par objets Principes et concepts Etude de Smalltalk.
Cours 4 (14 octobre) Héritage. Chapitre III Héritage.
Chapitre VII Techniques plus avancées à travers le concept de classe.
Héritage Conception par Objet et programmation Java
La gestion des bases de données
Introduction à la Programmation Orientée Objet
Master 1 SIGLIS Jave Lecteur Stéphane Tallard Chapitre 5 – Correction TD.
Transcription de la présentation:

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

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.

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.

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é.

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.

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.

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.

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

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

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

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

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

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

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

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+

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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).

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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);

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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