Chapitre 15. Héritage



Documents pareils
Pour signifier qu'une classe fille hérite d'une classe mère, on utilise le mot clé extends class fille extends mère

INFO-F-105 Language de programmation I Séance VI

et Programmation Objet

Encapsulation. L'encapsulation consiste à rendre les membres d'un objet plus ou moins visibles pour les autres objets.

Prénom : Matricule : Sigle et titre du cours Groupe Trimestre INF1101 Algorithmes et structures de données Tous H2004. Loc Jeudi 29/4/2004

Chapitre 2. Classes et objets

Héritage presque multiple en Java (1/2)

C++ COURS N 2 : CLASSES, DONNÉES ET FONCTIONS MEMBRES Classes et objets en C++ Membres d'une classe Spécification d'une classe Codage du comportement

Génie Logiciel I. Cours VI - Typage statique / dynamique, fonctions virtuelles et classes abstraites, flots d entrées / sorties, et string

Introduction à l héritage en C++

I. Introduction aux fonctions : les fonctions standards

Cours de C++ François Laroussinie. 2 novembre Dept. d Informatique, ENS de Cachan

Programmation par les Objets en Java

C++ Programmer. en langage. 8 e édition. Avec une intro aux design patterns et une annexe sur la norme C++11. Claude Delannoy

Claude Delannoy. 3 e édition C++

Premiers Pas en Programmation Objet : les Classes et les Objets

Programmer en JAVA. par Tama

Plan Pédagogique du cours

RAPPELS SUR LES METHODES HERITEES DE LA CLASSE RACINE Object ET LEUR SPECIALISATION (i.e. REDEFINITION)

Cours 1: Java et les objets

Introduction à C++ et à wxwidgets

Chapitre 10. Les interfaces Comparable et Comparator 1

Une introduction à Java

Rappel. Analyse de Données Structurées - Cours 12. Un langage avec des déclaration locales. Exemple d'un programme

Chapitre VI- La validation de la composition.

Introduction à la programmation Travaux pratiques: séance d introduction INFO0201-1

Polymorphisme, la classe Object, les package et la visibilité en Java... 1

Généralités sur le Langage Java et éléments syntaxiques.

Cours d initiation à la programmation en C++ Johann Cuenin

Informatique I. Sciences et Technologies du Vivant (Semestre 1)

LMI 2. Programmation Orientée Objet POO - Cours 9. Said Jabbour. jabbour@cril.univ-artois.fr

Java Licence Professionnelle Cours 7 : Classes et méthodes abstraites


Programmation C++ (débutant)/instructions for, while et do...while

LE LANGAGE C++ ENAC 1997 A. DANCEL

Création d objet imbriqué sous PowerShell.

Java Licence Professionnelle CISII, Cours 2 : Classes et Objets

Trier les ventes (sales order) avec Vtiger CRM

Rafraichissement conditionné d'une page en.net

Seance 2: En respectant la méthode de programmation par contrat, implémentez les autres fonctions de jeu.

Programmation Objet - Cours II

Licence Bio Informatique Année Premiers pas. Exercice 1 Hello World parce qu il faut bien commencer par quelque chose...

TP1 : Initiation à Java et Eclipse

.NET - Classe de Log

Programmation Orientée Objet en C#

Avertissement : Ce cours suppose la connaissance et la maîtrise du langage C CONTENU DU COURS BIBLIOGRAPHIE

Module.NET 3 Les Assemblys.NET

Département Automatisation et Informatisation Année Programmation en C++ Institut des Sciences et Techniques de l Ingénieur d Angers

TP n 2 Concepts de la programmation Objets Master 1 mention IL, semestre 2 Le type Abstrait Pile

Lambda! Rémi Forax Univ Paris-Est Marne-la-Vallée

30.avr.10 Présentation miniprojet. 9.mars.10 Cours 3 4.mai.10 Cours C mars.10 Cours 4 11.mai.10 Cours C++ 2

Langage Java. Classe de première SI

Éléments d informatique Cours 3 La programmation structurée en langage C L instruction de contrôle if

IRL : Simulation distribuée pour les systèmes embarqués

Le langage C++ (partie I)

1. Introduction Création d'une macro autonome Exécuter la macro pas à pas Modifier une macro... 5

CRÉER UNE BASE DE DONNÉES AVEC OPEN OFFICE BASE

Cours intensif Java. 1er cours: de C à Java. Enrica DUCHI LIAFA, Paris 7. Septembre Enrica.Duchi@liafa.jussieu.fr

Installation et paramétrage. Accès aux modèles, autotextes et clip- art partagés

C est quoi un tableur?

Programmation avec des objets : Cours 7. Menu du jour

Dessiner dans Galaad FRANÇOIS PALLUT

SHERLOCK 7. Version du 01/09/09 JAVASCRIPT 1.5

Programmation stochastique

COMPARAISONDESLANGAGESC, C++, JAVA ET

Classes et Objets en Ocaml.

Projet L1, S2, 2015: Simulation de fourmis, Soutenance la semaine du 4 mai.

Présentation du langage et premières fonctions

les Formulaires / Sous-Formulaires Présentation Créer un formulaire à partir d une table...3

Programme Compte bancaire (code)

Polycopié Cours Programmation Orientée Objet sous Java Programme : Filière SMI S5

1.6- Génération de nombres aléatoires

P r ob lé m a t iq u e d e la g é n é r icit é. Pr in cip e d e la g é n é r icit é e n Ja v a ( 1 /3 )

2 Grad Info Soir Langage C++ Juin Projet BANQUE

TD Objets distribués n 3 : Windows XP et Visual Studio.NET. Introduction à.net Remoting

Guide de Migration du Serveur IceWarp

Programmation en C/C++

Guide Utilisateur - Guide général d'utilisation du service via Zdesktop ou Webmail v.8. Powered by. - media-2001.communication &.

Initiation à JAVA et à la programmation objet.

Apprendre la Programmation Orientée Objet avec le langage Java (avec exercices pratiques et corrigés)

Cours d Algorithmique et de Langage C v 3.0

ALGORITHMIQUE ET PROGRAMMATION ORIENTEE OBJET

Mysql. Les requêtes préparées Prepared statements

Date M.P Libellé Catégorie S.Catégorie Crédit Débit Solde S.B

Programmation système I Les entrées/sorties

Auto-évaluation Programmation en Java

Reporting Services - Administration

Tp 1 correction. Structures de données (IF2)

INITIATION AU LANGAGE C SUR PIC DE MICROSHIP

ETUDE DE CAS en UML : GESTION DES COMMANDES DE PIECES FABRIQUEES PAR LA SOCIETE C

Le langage C++ est un langage de programmation puissant, polyvalent, on serait presque tenté de dire universel, massivement utilisé dans l'industrie

JAVA TD0. Prise en main du langage Environnement de base JAVA 1

2 e édition JAVA 5 et 6. Jérôme Bougeault. TSoft et Groupe Eyrolles, 2003, 2008, ISBN :

Corrigés des premiers exercices sur les classes

Guide Utilisateur - Guide général d'utilisation du service via Zdesktop ou Webmail v.8. Powered by. Version EXOCA 1

Le langage C. Séance n 4

Généralités. javadoc. Format des commentaires. Format des commentaires. Caractères spéciaux. Insérer du code

La programmation des PIC en C. Les fonctions, les interruptions.

Brefs rappels sur la pile et le tas (Stack. / Heap) et les pointeurs

Info0101 Intro. à l'algorithmique et à la programmation. Cours 3. Le langage Java

Transcription:

Chapitre 15 : Héritage 229 Chapitre 15 Héritage Chapitre 15 : Héritage 230 1. Généralités - L'héritage est le troisième des paradigmes de la programmation orientée objet (le 1 er étant l'encapsulation, le 2 e la structure de classe). - L'emploi de l'héritage conduit à un style de programmation par raffinements successifs et permet une programmation incrémentielle effective. - L'héritage peut être simple ou multiple. - Il représente la relation: EST-UN Un chat est un animal Une moto est un véhicule Un cercle est une forme - Alors que l'objet membre représente la relation: A-UN Une voiture a un moteur - L'héritage est mis en œuvre par la construction de classes dérivées.

Chapitre 15 : Héritage 231 - Le graphe de l'héritage est comme suit: animal véhicule chat chien oiseau avion voiture moto de course décapotable - La classe animal est la classe de base (classe supérieure), - Les classes chat, chien et oiseau sont des classes dérivées (sous-classes). Chapitre 15 : Héritage 232 2. Une classe dérivée - Une classe dérivée modélise un cas particulier de la classe de base et, est donc enrichie d'informations supplémentaires. - La classe dérivée possède les propriétés suivantes: contient les données membres de la classe de base, peut en posséder de nouvelles, possède (à priori) les méthodes de sa classe de base, peut redéfinir (masquer) certaines méthodes, peut posséder de nouvelles méthodes. - La classe dérivée hérite des membres de la classe de base. véhicule Héritage avion Classe de base vitesse nombre passagers Membres hérités nombre de moteurs Classe héritée Propre à un avion

Chapitre 15 : Héritage 233 3. Syntaxe de l'héritage class classe_dérivée:protection classe_de_base {/* etc. */ - Les types de protections sont : «public», «protected», «private». Chapitre 15 : Héritage 234 4. Déclarations #include <iostream> using namespace std; class vehicule { double vitesse; int nbre_passagers; ; // Fonction remplace le constructeur. void init_vehicule(double v,int np) { vitesse = v; nbre_passagers = np; // Pour afficher les membres private. void affiche() { cout << "vitesse: " << vitesse << \ " ; nbre_passagers: " << nbre_passagers << endl;

Chapitre 15 : Héritage 235 // avion hérite publiquement de véhicule. class avion:public vehicule { int nbre_moteurs; // fonction remplace le constructeur void init_avion(int nm) { nbre_moteurs = nm; ; // moto hérite publiquement de véhicule. class moto:public vehicule { double cylindree; // Fonction remplace le constructeur void init_moto(double cy) { cylindree = cy; ; int main() { vehicule v; avion boeing; moto suzuki; return 0; Chapitre 15 : Héritage 236 5. Accès aux membres hérités - Si la classe dérivée hérite publiquement de la classe de base, les membres de la classe dérivée auront accès aux membres publics (champs et méthodes) de la classe de base, par contre, ils n'auront pas accès aux membres privés de la classe de base. - Pour l'exemple du paragraphe 4, nous pouvons écrire la fonction main suivante: int main() { avion boeing767; boeing767.init_avion(2); // Fonctions héritées de la classe de base. boeing767.init_vehicule(950,200); boeing767.affiche(); // affiche: 950, 200 mais pas 2. // Err: accès à des données privées de la classe de base. boeing767.nbre_moteurs=4; boeing767.vitesse=800; // Err: accès à des données privées de la classe dérivée. boeing767.nbre_passagers=188; return 0;

Chapitre 15 : Héritage 237 6. Redéfinition des fonctions membres - La fonction affiche de la page précédente est membre de la classe de base véhicule. - Elle n'affiche que les membres privés de cette classe. - On ne peut pas donc afficher le nombre de moteurs. - Pour faire cela, nous allons définir dans la classe dérivée une fonction portant le même nom et, qui aura pour rôle d'afficher les données privées de la classe dérivée. - On parle alors de redéfinition (ou surcharge) d'une fonction de la classe de base. class avion:public vehicule { int nbre_moteurs; // Fonction remplace le constructeur void init_avion(int nm) { nbre_moteurs = nm; // Pour afficher les membres private void affiche() { cout << "vitesse: " << vitesse << " ; nbre_passagers: "\ << nbre_passagers << " ; nbre_moteurs: "\ << nbre_moteurs << endl; ; Chapitre 15 : Héritage 238 - La fonction affiche, dans ce cas-là, ne va pas fonctionner. Il y aura erreur de compilation. - En effet, la classe avion n'a pas le droit d'accéder aux membres privés de la classe de base. - Comment afficher alors les données privées de la classe de base et celles de la classe dérivée, cela par l'utilisation d'une fonction dans la classe dérivée? class avion:public vehicule { int nbre_moteurs; ; // Fonction remplace le constructeur. void init_avion(int nm) { nbre_moteurs = nm; // Pour afficher les membres private. void affiche() { // appel de la fonction affiche de la classe de base. vehicule::affiche(); cout << "nbre_moteurs: " << nbre_moteurs << endl;

Chapitre 15 : Héritage 239 - Puisque affiche de la classe de base (ici véhicule) est accessible, on fera donc appel à elle à partir de la fonction affiche de la classe dérivée. - La nouvelle définition de avion::affiche cache l'ancienne définition (celle de véhicule::affiche) accessible via héritage. int main() { avion boeing767; boeing767.init_avion(2); // Fonctions héritées de la classe de base boeing767.init_vehicule(950,200); // Fonction de la classe dérivée // Appel de avion::affiche et non pas vehicule::affiche boeing767.affiche(); return 0; Chapitre 15 : Héritage 240 7. Constructeurs et destructeurs - Pour construire un avion, il faut construire d'abord un véhicule. - Le constructeur de la classe de base (véhicule) est donc appelé avant le constructeur de la classe dérivée (avion). - De façon symétrique, le destructeur de la classe de base (véhicule) est appelé après le destructeur de la classe dérivée (avion). #include <iostream> using namespace std; class vehicule { double vitesse; int nbre_passagers; // Constructeur vehicule(double v,int np) { vitesse = v; nbre_passagers = np; ~vehicule() { // Pour afficher les membres private. void affiche() { cout << "vitesse: " << vitesse << \ " ; nbre_passagers: " << nbre_passagers << endl; ;

Chapitre 15 : Héritage 241 class avion:public vehicule { int nbre_moteurs; // Constructeur de la classe dérivée avion(int nm,double v,int np):vehicule(v,np) { nbre_moteurs = nm; void affiche() { vehicule::affiche(); cout << "nbre_moteurs: " << nbre_moteurs << endl; ; int main() { avion boeing767(2,950,200); boeing767.affiche(); return 0; - Si la classe de base a un constructeur autre que celui par défaut, la classe dérivée doit avoir un constructeur. Sinon il est impossible de créer un objet. - Si dans l'appel du constructeur de la classe dérivée, le nom du constructeur de la classe de base n'est pas mentionné explicitement, le constructeur par défaut de la classe de base sera pris en compte. - Si la classe de base ne possède pas ce constructeur, il y aura alors une erreur de compilation. - Question: citez dans quels cas la classe de base ne possédera pas de constructeur par défaut? Chapitre 15 : Héritage 242 8. Contrôle des accès - Les droits d'accès protègent les données et les méthodes et réalisent aussi l'encapsulation. - Les droits d'accès sont accordés aux fonctions membres ou aux fonctions globales. - L'unité de protection est la classe: tous les objets de la classe bénéficient de la même protection. - Il y a 3 catégories de protection: un membre public est accessible à toute fonction, un membre private n'est accessible qu'aux fonctions membres de la classe ou aux fonctions amies, un membre protected n'est accessible qu'aux fonctions membres de la classe de base ou des classes dérivées ou aux fonctions amies. #include <iostream> using namespace std; class simule { int a; void fa(); protected: int b; void fb(); int c; void fc(); ;

Chapitre 15 : Héritage 243 class vide:public simule{ void test() { cout << a << endl; // Erreur car a est déclarée private. fa(); // Erreur car fa est déclarée private. // La fonct test accède aux données public et protected. ; cout << b << endl; // ok car b est déclarée protected. fb(); // ok car fb est déclarée protected. cout << c << endl; // ok car c est déclarée public. fc(); // ok car fc est déclarée public. int main() { simule rien; cout << rien.a << endl; // Err car a est déclarée private. rien.fa(); // Err car fa est déclarée private. cout << rien.b << endl; // Err car b est protected. rien.fb(); // Erreur car fb est déclarée protected. cout << rien.c << endl; // ok car c est déclarée public. rien.fc(); // ok car fc est déclarée public. return 0; Chapitre 15 : Héritage 244 Mode de dérivation Public protected private statut dans public Public protected private la classe de protected protected protected private base private private private private - Mode de dérivation: le plus utilisé protected: rarement utilisé private: pour réécrire complètement l'interface. De ce fait, la notion EST-UN disparaît. On ne parle plus donc d'héritage.

Chapitre 15 : Héritage 245 9. Constructeur de recopie - On doit recopier les champs de la classe dérivée et ceux de la classe de base. class B { /* classe de base */ ; class D:public class B { /* classe dérivée */ ; - Deux cas peuvent se présenter: 1. la classe D n'a pas de constructeur de recopie: - Les appels des constructeurs se feront comme suit: constructeur de recopie par défaut de la classe D, constructeur de recopie explicite ou par défaut de la classe B. Chapitre 15 : Héritage 246 2. la classe D a un constructeur de recopie: - Les appels des constructeurs se feront comme suit: le compilateur appelle ce constructeur de recopie. C'est à ce constructeur de recopie d'appeler celui de la classe de base (s'il veut, et habituellement on veut qu'il le fasse). Si l on ne fait pas cet appel et, si la classe de base n'a pas de constructeur de recopie explicite, alors c'est le constructeur par défaut qui est appelé. Si la classe de base n'en possède pas un, c'est le constructeur avec arguments par défaut qui est appelé. S'il n'en existe pas un, il y aura erreur de compilation. #include <iostream> using namespace std; class vehicule { double vitesse; int nbre_passagers; ; vehicule(double,int); // constructeur. vehicule(const vehicule& v2); // constructeur de recopie. ~vehicule(); // destructeur. // Pour afficher les membres private. void affiche();

Chapitre 15 : Héritage 247 // avion hérite publiquement de véhicule. class avion:public vehicule { int nbre_moteurs; avion(int,double,int); // constructeur. avion(const avion&); // constructeur de recopie. ~avion(); // destructeur. // Pour afficher les membres private. void affiche(); ; // Constructeur de véhicule. vehicule::vehicule(double v,int np) { vitesse = v; nbre_passagers = np; cout << "C.Veh.: " << this << endl; // Destructeur de véhicule. vehicule::~vehicule() { cout << "D.Veh.: " << this << endl; // Constructeur de recopie. vehicule::vehicule(const vehicule& v2) { vitesse = v2.vitesse; nbre_passagers = v2.nbre_passagers; cout << "R.Veh.: " << this << endl; Chapitre 15 : Héritage 248 // Constructeur d avion qui appelle le constr. de véhicule. avion::avion(int nm,double v,int np):vehicule(v,np) { nbre_moteurs = nm; cout << "C.Av.: " << this << endl; // Constructeur de recopie d avion qui appelle explicitement // le constructeur de recopie de véhicule. // a2 est converti en objet du type véhicule. avion::avion(const avion& a2):vehicule(a2) { nbre_moteurs = a2.nbre_moteurs; cout << "R.Av.: " << this << endl; // Destructeur de avion. avion::~avion() { cout << "D.Av.: " << this << endl; // Fonction pour afficher les données private // de la classe de véhicule. void vehicule::affiche() { cout << "vitesse: " << vitesse << " ; nbre_passagers: " << nbre_passagers << endl;

Chapitre 15 : Héritage 249 // Fonction pour afficher les données private // des classes base et dérivée. void avion::affiche() { vehicule::affiche(); // affiche de la classe de base. cout << "nbre_moteurs: " << nbre_moteurs << endl; int main() { vehicule va(110,4); // création de l'objet va vehicule vcopie(va); // création par recopie // de l'objet vcopie // Création de l'objet aa du type avion, // appelle aussi le constructeur de véhicule. avion aa(2,200,180); // Création de l'objet bcopie du type avion, // appelle aussi le constructeur de recopie de véhicule. avion bcopie(aa); // Affichage en sortie. vcopie.affiche(); bcopie.affiche(); return 0; Chapitre 15 : Héritage 250 - Sortie: C.Veh.: 0xbffff7ac const objet va. R.Veh.: 0xbffff7a0 const de recopie pour vcopie. C.Veh.: 0xbffff790 const objet aa: appelle d'abord const véhicule, C.Av.: 0xbffff790 puis le constructeur avion. R.Veh.: 0xbffff780 const de recopie pour bcopie: appelle d'abord const de recopie de véhicule, R.Av.: 0xbffff780 puis const de recopie pour l'objet bcopie. vitesse: 110 ; nbre_passagers: 4 fonct affiche de véhicule. vitesse: 200 ; nbre_passagers: 180 fonct affiche de avion. nbre_moteurs: 2 D.Av.: 0xbffff780 destructeur de bcopie, puis D.Veh.: 0xbffff780 celui de sa classe de base. D.Av.: 0xbffff790 destructeur de aa, puis D.Veh.: 0xbffff790 celui de sa classe de base. D.Veh.: 0xbffff7a0 destructeur de vcopie. D.Veh.: 0xbffff7ac destructeur de va.

Chapitre 15 : Héritage 251 10. Opérateur d'affectation - Deux cas peuvent se présenter: 1. La classe dérivée n'a pas surdéfini l'opérateur d'affectation = - Dans ce cas, le compilateur appelle: - Sinon: o l'opérateur = de la classe de base (par défaut ou surdéfini). o l'opérateur = par défaut de la classe dérivée. 2. La classe dérivée a surdéfini l'opérateur d'affectation = - Dans ce cas, le compilateur appelle seulement cet opérateur. À lui d'appeler l'opérateur = de la classe de base s'il veut (habituellement oui!). - Pour l'exemple du paragraphe 9, nous obtenons ce qui suit: Chapitre 15 : Héritage 252 class vehicule { double vitesse; int nbre_passagers; // etc. vehicule& operator=(const vehicule&); ; // avion hérite publiquement de véhicule. class avion:public vehicule { int nbre_moteurs; // etc. avion& operator=(const avion&); ; // Opérateur d'affectation de la classe de base. vehicule& vehicule::operator=(const vehicule& v2) { if (this!= &v2) { vitesse = v2.vitesse; nbre_passagers = v2.nbre_passagers; cout << "A.Veh.: " << this << endl; return *this;

Chapitre 15 : Héritage 253 // Opérateur d'affectation de la classe dérivée. avion& avion::operator=(const avion& a2) { if (this!= &a2) { vehicule::operator=(a2); nbre_moteurs = a2.nbre_moteurs; cout << "A.av.: " << this << endl; return *this; int main() { vehicule v1(110,4); vehicule v2(240,2); v2 = v1; opérateur d'affectation de la classe véhicule. avion ava(2,200,180); avion avb(4,300,250); avb = ava; opérateur d'affectation de la classe de base, puis de la classe dérivée. V2.affiche(); avb.affiche(); return 0; Chapitre 15 : Héritage 254 - Une autre manière d'écrire l'opérateur d'affectation de la classe dérivée est comme suit: avion& avion::operator=(avion& a2) { if (this!= &a2) { vehicule* ptrv = this; vehicule* ptra = &a2; // utilise l'opérateur d'affectation de véhicule. *ptrv = *ptra; nbre_moteurs = a2.nbre_moteurs; cout << "A.av.: " << this << endl; return *this; - Nous avons modifié l'entête de la fonction operator= pour passer l'argument comme une variable non constante à cause de l instruction suivante: vehicule* ptra = &a2; // a2 ne peut pas être constante. - Question: comment faudrait-il réécrire ce code pour que l'argument a2 reste constant?

Chapitre 15 : Héritage 255 11. Typage statique vs. Typage dynamique - Type statique d'une variable: type à la compilation, type déclaré. - Type dynamique d'une variable: type à l'exécution, type en mémoire. - Par défaut, nous utilisons le typage statique car il est moins coûteux (espace/temps). - Nous pouvons utiliser aussi le typage dynamique en employant le mot clé réservé: dynamic_cast. 12. Compatibilité entre objets d'une classe de base et objets d'une classe dérivée - Un objet d'une classe dérivée peut toujours être utilisé au lieu d'un objet de sa classe de base. (N est applicable que dans le cas de la dérivation public). - Par exemple, un avion est un véhicule. Mais l'inverse n'est pas vrai, un véhicule n'est pas nécessairement un avion. - Soit l'exemple suivant: vehicule v(300,4); avion a(800,350,3); vehicule* ptrv; avion* ptra; ptrv = &v; ptra = &a; Chapitre 15 : Héritage 256 1 er cas: v = a - Conversion implicite de tout avion EST-UN véhicule. Le compilateur fait une copie en ignorant les membres excédentaires (nbre_moteurs). - Supposez que tous les membres des classes base et dérivée ont été déclarés public, nous aurons ce qui suit: cout << v.vitesse << end; // ok. cout << v.nbre_moteurs << endl; // erreur car véhicule n'a pas d'information sur le nombre de moteurs. 2 e cas: a = v // erreur - Un véhicule n'est pas forcément un avion. On ne peut pas deviner quelles seront les valeurs manquantes (dans cet exemple: nbre_moteurs). Un véhicule n'a pas toutes les données d'un avion.

Chapitre 15 : Héritage 257 3 e cas: ptrv = ptra // ok, - Mais cout << ptrv->vitesse << endl; // ok cout << ptrv->nbre_moteurs << endl; // erreur - À la compilation, ptrv pointe sur un véhicule. Par la suite, même si ptrv prend le pointeur de avion, il ne reconnaît pas les autres éléments (ne seront pas accessibles, ne les reconnaît pas). Chapitre 15 : Héritage 258 4 e cas: ptra = ptrv // erreur - Pour que ça marche, il faut "caster" (forcer le changement de type) le pointeur ptrv, c.-à-d.: ptra = (avion *) ptrv // ok cout << ptra.nbre_moteurs << endl; - Il affiche n'importe quelle valeur (par exemple: -1073743912) car la variable nbre_moteurs n'a pas été initialisée (ne contient aucune donnée). Récapitulatif Conversion de classe dérivée à classe de base // ok Conversion de classe de base à classe dérivée // Erreur, conversion interdite Conversion de (classe dérivée)* à (classe de base)* // ok Conversion de (classe de base)* à (classe dérivée)* // acceptée avec un cast explicite.

Chapitre 15 : Héritage 259 Réponse à la question posée au paragraphe 7: dans le cas où nous avons défini explicitement un constructeur (sans valeurs par défaut) dans cette classe de base (masque la présence du constructeur par défaut) et nous n'avons pas défini en plus un constructeur sans arguments (pour recréer le constructeur par défaut). Réponse à la question posée au paragraphe 10: il faut réécrire le code de l'opérateur d'affectation comme suit: avion& avion::operator=(const avion& a2) { if (this!= &a2) { vehicule* ptrv = this; vehicule* ptra = const_cast <avion*> (&a2); // Utilise l'opérateur d'affectation de véhicule. *ptrv = *ptra; nbre_moteurs = a2.nbre_moteurs; cout << "A.av.: " << this << endl; return *this; Chapitre 15 : Héritage 260