L’héritage en C++
Philippe d’Anfray GIP RENATER
2006-2007
Philippe.d-Anfray@renater.fr
Formation d’Ing´enieurs de l’Instit...
Privé/Public (1)
Rappel: lors de la définition des objets, il y a toujours deux points de
vues et donc deux statuts possibl...
Privé/Public (5)
Pour des raisons d’optimisations, le concepteur de DERIVEE a
souvent besoin d’ accèder à la partie privée...
Héritage/ Constructeurs-Destructeurs (2)
Un problème, celui des arguments:
class BASE class DERIVEE : public BASE
{ ... { ...
Fonctions virtuelles (1)
Soit une classe matrice_carree. Je sais définir les méthodes mais
la forme des données n’est pas fi...
Fonctions virtuelles (5)
On ira chercher à l’exécution la réalisation de inverser
correspondant au type réel de l’instance...
Héritage multiple/duplication (1)
Le graphe d’héritage peut amener la duplication d’une classe de
base:
liste_chaînée
list...
C++/Conclusions (1)
La généricité est utile pour des logiciels de grande taille et dans
l’optique réutilisation:
les types...
Prochain SlideShare
Chargement dans…5
×

2006 2007-heritage-en-c++

257 vues

Publié le

Publié dans : Formation
0 commentaire
0 j’aime
Statistiques
Remarques
  • Soyez le premier à commenter

  • Soyez le premier à aimer ceci

Aucun téléchargement
Vues
Nombre de vues
257
Sur SlideShare
0
Issues des intégrations
0
Intégrations
1
Actions
Partages
0
Téléchargements
6
Commentaires
0
J’aime
0
Intégrations 0
Aucune incorporation

Aucune remarque pour cette diapositive

2006 2007-heritage-en-c++

  1. 1. L’héritage en C++ Philippe d’Anfray GIP RENATER 2006-2007 Philippe.d-Anfray@renater.fr Formation d’Ing´enieurs de l’Institut Galil´ee MACS 2 GIP RENATER Philippe d’Anfray Objets en C++ 2006-2007 – p. 1/30 Héritage/Définition (1) On peut dériver une classe à partir d’une autre. La classe dérivée hérite de toutes les caractéristiques de la classe dite de base. class BASE class DERIVEE : PUBLIC BASE { { int i, j; int k, l; ... ... public: public: void f_base (...); void f_derivee (...); ... ... }; }; ... On intéressera essentiellement à l’héritage “public”. GIP RENATER Philippe d’Anfray Objets en C++ 2006-2007 – p. 2/30 Héritage/Définition (2) Une instance de la classe dérivée possède en plus des siens toutes les données et toutes les méthodes de la classe de base. ... int main() { DERIVEE d1, d2; d1.f_base (...); // Possible, vient de BASE d1.f_derivee (..); // OK aussi vient de DERIVE } On peut redéfinir le comportement de l’objet en surchargeant les méthodes Attention. . . voir plus loin. . . GIP RENATER Philippe d’Anfray Objets en C++ 2006-2007 – p. 3/30 Héritage/Définition (3) Le processus peut se répéter, on obtient des graphes d’héritage Héritage simple: un arbre, Héritage multiple: graphe acyclique. Base Dérivé_2Dérivé_1 Dérivé_3 Dérivé_4 Dérivé_2Dérivé_1 Dérivé_3 Dérivé_4 Base_1 Base_2 Arbre d’héritage (simple) Graphe d’héritage (multiple) GIP RENATER Philippe d’Anfray Objets en C++ 2006-2007 – p. 4/30
  2. 2. Privé/Public (1) Rappel: lors de la définition des objets, il y a toujours deux points de vues et donc deux statuts possibles pour les champs: le programmeur concepteur/développeur, partie “privée”; le programmeur utilisateur, partie “public”. Comment ces notions passent-elles à travers les mécanismes d’héritage ? GIP RENATER Philippe d’Anfray Objets en C++ 2006-2007 – p. 5/30 Privé/Public (2) Règle générale: La partie privée de la classe de base reste inaccessible à la classe dérivée. Le concepteur de DERIVEE n’a pas accès à la partie privée de la classe de BASE sauf si elle est déclarée explicitement amie. Tout ce qui peut modifier la partie privée d’une classe doit être déclaré dans le corps de la classe. GIP RENATER Philippe d’Anfray Objets en C++ 2006-2007 – p. 6/30 Privé/Public (3) Cas de l’héritage “privé”, la partie publique de BASE devient privée pour DERIVEE. Le concepteur de DERIVEE y a accès pas l’utilisateur. class BASE class DERIVEE:BASE { { private://dev. BASE private:// dev. DERIVEE ... ... public: //util. BASE public: // util. DERIVEE ... //dev. DERIVEE ... }; }; Mais on s’intéresse plutôt à l’héritage “public” GIP RENATER Philippe d’Anfray Objets en C++ 2006-2007 – p. 7/30 Privé/Public (4) La partie publique de BASE peut être rendus accessible aux utilisateurs de DERIVEE: héritage “public”. class BASE class DERIVEE:public BASE { { private://dev. BASE private:// dev. DERIVEE ... ... public: //util. BASE public: // util. DERIVEE ... //dev. DERIVEE ... ... //util. DERIVEE }; ... //car public }; GIP RENATER Philippe d’Anfray Objets en C++ 2006-2007 – p. 8/30
  3. 3. Privé/Public (5) Pour des raisons d’optimisations, le concepteur de DERIVEE a souvent besoin d’ accèder à la partie privée de BASE. Cela donne lieu à deux types d’excès: le tout ami: plus aucune protection; le tout public: visibilité totale. Problème: on perd la séparation spécification/réalisation ! GIP RENATER Philippe d’Anfray Objets en C++ 2006-2007 – p. 9/30 Protégé (1) Il existe un statut intermédiaire: le champ protégé: class BASE class DERIVEE: public BASE { private: //dev. BASE { ... private: protected://dev. BASE ... ... //dev. DERIVEE public: public: //util. BASE ... ... //dev. DERIVEE }; }; Un champ protégé de BASE est accessible aux développeurs de DERIVEE pas aux utilisateurs. GIP RENATER Philippe d’Anfray Objets en C++ 2006-2007 – p. 10/30 Héritage / Fonctions amies (1) Les relations d’amitié ne se transmettent pas par héritage. class BASE class DERIVEE: public BASE { { private: ... private: protected: ... ... public: public: friend void ff ... (BASE& b...); ... ... }; }; ff n’est pas amie de DERIVEE. GIP RENATER Philippe d’Anfray Objets en C++ 2006-2007 – p. 11/30 Héritage/ Constructeurs-Destructeurs (1) Deux règles simples: Le constructeur de la classe de base si il existe est appelé avant le constructeur de la classe dérivée. Le destructeur de la classe de base si il existe est appelé après le destructeur de la classe dérivée. Se généralise si il y a plusieurs dérivations. GIP RENATER Philippe d’Anfray Objets en C++ 2006-2007 – p. 12/30
  4. 4. Héritage/ Constructeurs-Destructeurs (2) Un problème, celui des arguments: class BASE class DERIVEE : public BASE { ... { ... public: public: // avec arguments // avec arguments BASE DERIVEE (int b_1...float b_n) (float d_1...char* d_m); {... ... } }; }; Je dois pouvoir utiliser DERIVEE sans a priori connaître BASE. GIP RENATER Philippe d’Anfray Objets en C++ 2006-2007 – p. 13/30 Héritage/ Constructeurs-Destructeurs (3) Quand je réalise le constructeur de DERIVEE je dois donner les valeurs des arguments du constructeur de BASE: DERIVEE::DERIVEE (float d_1, ...char* d_m) :BASE (val_b_1...val_b_n); // // val_b_1...val_b_n sont les valeurs // des arguments b_1...b_n passes au // constructeur de la classe BASE // pour construire un objet DERIVEE { ... ; } Les destructeurs n’ont pas d’argument, pas de problème(s). GIP RENATER Philippe d’Anfray Objets en C++ 2006-2007 – p. 14/30 Polymorphisme (1) Je peux redéfinir une fonction: class BASE class DER:public BASE int main() { { { ... ... DER d; public: public: // ff de DER void ff(..); void ff (..); d.ff(..); ... ... // ff de BASE }; }; d.BASE::ff(..); } Notez le come-back de l’opérateur :: Les redéfinitions de fonctions sont dangereuses à manipuler... GIP RENATER Philippe d’Anfray Objets en C++ 2006-2007 – p. 15/30 Polymorphisme (2) Un pointeur sur une instance d’une classe dérivée peut être considéré comme un pointeur sur une instance de la classe de base. Dans l’autre sens le typage explicite est obligatoire . main() { BASE *p_base; DERIVEE *p_derivee; ... // licite du particulier au general p_base = p_derivee; // du general au particulier: requete explicite p_derivee = (DERIVEE *) p_base; ... } GIP RENATER Philippe d’Anfray Objets en C++ 2006-2007 – p. 16/30
  5. 5. Fonctions virtuelles (1) Soit une classe matrice_carree. Je sais définir les méthodes mais la forme des données n’est pas fixée à priori: Matrice Symétrique Carrée Matrice Matrice tridiagonale ... ......... Matrice Pleine On aura une réalisation différente pour chaque classe dérivée. notion d’archétype. GIP RENATER Philippe d’Anfray Objets en C++ 2006-2007 – p. 17/30 Fonctions virtuelles (2) Fonction virtuelles: class matrice_carree { // donnees: pas les elements public: virtual inverser(..); ... } Ceci signifie que je vais (éventuellement) redéfinir la méthode inverser dans les classes dérivées. GIP RENATER Philippe d’Anfray Objets en C++ 2006-2007 – p. 18/30 Fonctions virtuelles (3) class matrice_symetrique: public matrice_carree { // donnes privees public: ... virtual inverser (...); }; class matrice_tridiagonale: public matrice_carree { // donnees privees public: ... virtual inverser (...); }; GIP RENATER Philippe d’Anfray Objets en C++ 2006-2007 – p. 19/30 Fonctions virtuelles (4) Fonction virtuelle, plus que la simple surcharge: mécanisme de la liaison dynamique. Une application peut utiliser matrice_carree sans connaître a priori les types qui seront dérivés: void f_appli (matrice_carree& m, ...) { ... m.inverser (); // on travaille sur le ... // type matrice_carree } GIP RENATER Philippe d’Anfray Objets en C++ 2006-2007 – p. 20/30
  6. 6. Fonctions virtuelles (5) On ira chercher à l’exécution la réalisation de inverser correspondant au type réel de l’instance (celui de la déclaration). int main() { matrice_tridiagonale mt; // ici on utilisera pour "inverser" dans ‘‘f_appli’’ // la realisation de la classe derivee tridiagonale f_appli (mt, ..); ... } Si une fonction doit être redéfinie, utiliser une fonction virtuelle. GIP RENATER Philippe d’Anfray Objets en C++ 2006-2007 – p. 21/30 Fonctions virtuelles (6) On ira chercher à l’exécution la réalisation de la méthode correspondant au type réel de l’instance (celui de la déclaration). C’est pour cette raison que le destructeur doit être virtuel. N.B. le constructeur ne peut être virtuel. Attention en cas de “simple surcharge” le choix sera fait à la compilation. Problème: l’éventuel surcoût du mécanisme (compilateurs “dévirtualiseurs”). GIP RENATER Philippe d’Anfray Objets en C++ 2006-2007 – p. 22/30 Classe abstraite (1) Une fonction virtuelle pure ne reçoit aucune réalisation par défaut. Une classe qui contient au moins une fonction virtuelle pure est une classe abstraite. class ABSTRAITE //Notion d’archetype { ... public: virtual void info(..)=0;//virtuelle pure }; Il n’est pas possible d’instancier un objet de type ABSTRAITE. Il faut écrire des classes dérivées de ABSTRAITE. GIP RENATER Philippe d’Anfray Objets en C++ 2006-2007 – p. 23/30 Héritage multiple/ambiguités (1) Toutes les ambiguités d’accès doivent être levées à la compilation: class B_1 class B_2 class D: int main() {... {... public B_1, { public: public: public B_2 D vd; int i,ii; int* ii; { vd.i ..//OK de B_1 ... ... ... vd.B_1::ii//de B_1 }; }; }; vd.B_2::ii//de B_2 } Encore une fois, :: précise le référentiel. GIP RENATER Philippe d’Anfray Objets en C++ 2006-2007 – p. 24/30
  7. 7. Héritage multiple/duplication (1) Le graphe d’héritage peut amener la duplication d’une classe de base: liste_chaînée liste_de_A liste_de_B dérivé_A_B matrice_carree matrice_symétrique_définie_positive matrice_symétrique matrice_définie_positive Duplication souhaitable Duplication non souhaitable GIP RENATER Philippe d’Anfray Objets en C++ 2006-2007 – p. 25/30 Héritage multiple/duplication (2) Si on ne fait rien ==> duplication class GP class D1 class U: int main() {... :public GP public D1, { public: {... public D2 U u1; int i; }; { //GP via D1 ... ... u1.D1::i ... }; class D2 }; //GP via D2 public GP u1.D2::i ... {... } }; } L’utilisation de l’opérateur :: est obligatoire pour préciser le référentiel. GIP RENATER Philippe d’Anfray Objets en C++ 2006-2007 – p. 26/30 Héritage multiple/duplication (3) Pour éviter la duplication: notion de “classe virtuelle”. class GP class D1: class U: int main() {... public virtual GP public D1, { public: {... public D2 U u1; int i; }; { u1.i .. ... class D2: ... //un seul i }; public virtual G }; //(de GP) {... }; }; Problème: l’héritage virtual n’est ni une propriété de GP, ni une spécification de U. GIP RENATER Philippe d’Anfray Objets en C++ 2006-2007 – p. 27/30 Récapitulation-2 (1) Notions à bien comprendre: Héritage simple, multiple. privé/public/protégé. Fonctions virtuelles. Classes abstraites. Classes virtuelles. GIP RENATER Philippe d’Anfray Objets en C++ 2006-2007 – p. 28/30
  8. 8. C++/Conclusions (1) La généricité est utile pour des logiciels de grande taille et dans l’optique réutilisation: les types paramètres (template); l’héritage simple; l’héritage multiple (difficile à gérer). GIP RENATER Philippe d’Anfray Objets en C++ 2006-2007 – p. 29/30 C++/Conclusions (2) Le langage C++ offre beaucoup de possibilités. mais. . . il est aussi très “permissif”. Il est indispensable d’avoir une méthodologie: faire le “tri” (quelle caractéristique est utile à un moment donné). suivre une démarche de réalisation (les types, leurs relations mutuelles). GIP RENATER Philippe d’Anfray Objets en C++ 2006-2007 – p. 30/30

×