5i - PowerPoint PPT Presentation

About This Presentation
Title:

5i

Description:

Bien entendu, on doit avoir les droits d'acc s sur les membres de la classe de ... pf = &f; // Autoris . pm = pf; // Autoris . Les donn es et les ... – PowerPoint PPT presentation

Number of Views:25
Avg rating:3.0/5.0
Slides: 27
Provided by: park183
Category:
Tags: autorise

less

Transcript and Presenter's Notes

Title: 5i


1
5ième Classe (Mercredi, 3 Novembre)CSI2572
2
Héritage
  • Il est possible d'utiliser un objet d'une classe
    dérivée partout où l'on peut utiliser un objet
    d'une de ses classes mères. Les méthodes et
    données des classes mères appartiennent en effet
    par héritage aux classes filles. Bien entendu, on
    doit avoir les droits d'accès sur les membres de
    la classe de base que l'on utilise (l'accès peut
    être restreint lors de l'héritage).
  • il est possible de faire une affectation d'une
    classe dérivée vers une classe mère. Les données
    qui ne servent pas à l'initialisation sont
    perdues, puisque la classe mère ne possède pas
    les champs correspondants. En revanche, l'inverse
    est strictement interdit. En effet, les données
    de la classe fille qui n'existent pas dans la
    classe mère ne pourraient pas recevoir de valeur,
    et l'initialisation ne se ferait pas
    correctement.

3
Héritage
  • Les pointeurs des classes dérivées sont
    compatibles avec les pointeurs des classes mères.
    Cela signifie qu'il est possible d'affecter un
    pointeur de classe dérivée à un pointeur d'une de
    ses classes de base. Il faut bien entendu que
    l'on ait en outre le droit d'accéder à la classe
    de base, c'est-à-dire qu'au moins un de ses
    membres puisse être utilisé. Cette condition
    n'est pas toujours vérifiée, en particulier pour
    les classes de base dont l'héritage est private.
  • Un objet dérivé pointé par un pointeur d'une des
    classes mères de sa classe est considéré comme un
    objet de la classe du pointeur qui le pointe. Les
    données spécifiques à sa classe ne sont pas
    supprimées, elles sont seulement momentanément
    inaccessibles. C'est ce à quoi sert le mécanisme
    des méthodes virtuelles

4
class Mere public Mere(void)
Mere(void) class Fille public Mere
public Fille(void) Fille(void) Mere
m // Instanciation de deux objets. Fille f
mf //OK fm // ERREUR !! (ne compile pas).
5
Avec pointeurs
Mere pm, m Fille pf, f pf f //
Autorisé. pm pf // Autorisé. Les données et
les méthodes // de la classe fille ne sont plus
accessibles // avec ce pointeur pm est un
objet // de la classe mère. pfm // ILLÉGAL
il faut faire un cast pf(Fille ) m //
Cette fois, c'est légal, mais DANGEREUX ! // En
effet, les méthodes de la classe filles // ne
sont pas définies, puisque m est une classe //
mère.
6
Héritage virtual
  • L'utilisation d'un pointeur sur la classe de
    base pour accéder à une classe dérivée nécessite
    d'utiliser des méthodes virtuelles. En
    particulier, il est nécessaire de rendre virtuels
    les destructeurs. Par exemple, avec la définition
    donnée ci-dessus pour les deux classes, le code
    suivant est faux 
  • Mere pm
  • Fille pf new Fille
  • pm pf
  • delete pm // Appel du destructeur de la classe
    mère !

7
Héritage virtual
  • Pour résoudre le problème, il faut que le
    destructeur de la classe mère soit virtuel (il
    est inutile de déclarer virtuel le destructeur
    des classes filles) 
  • class Mere
  • public Mere(void)
  • virtual Mere(void)
  • Le bon destructeur est appelé, car le destructeur
    est déclaré virtual. En effet, l'opérateur delete
    recherche le destructeur à appeler dans la classe
    de l'objet le plus dérivé. De plus, l'opérateur
    delete restitue la mémoire de l'objet complet, et
    pas seulement celle du sous-objet référencé par
    le pointeur utilisé dans l'expression delete.

8
Héritage virtual
  • Lorsqu'on utilise la dérivation, il est donc
    très important de déclarer les destructeurs
    virtuels pour que l'opérateur delete utilise le
    vrai type de l'objet à détruire.
  • Bien sur, il est aussi nécéssaire d'utiliser le
    méchanisme virtuel dans toutes les situations ou
    une instance sera référée par un pointeur typé
    sur la classe mère de sa classe.

9
include ltiostream.hgt class A public
void foo()coutltlt "Afoo()"ltltendl class
B public A public void foo()coutltlt
"Bfoo()"ltltendl int main(void) A a B
b A p b A r b p-gtfoo() r.foo() a
b a.foo() return 0
Afoo() Afoo() Afoo()
10
class shape private char name public
shape(const char) shape(const shape)
shape operator(const shape) virtual
shape() // pure virtual function virtual
double area() const 0 const char
get_name() const
11
shapeshape(const char n) name(new
charstrlen(n)1) strcpy(name,n)
shape shapeoperator(const shape s)
delete name name new
charstrlen(s.name)1 strcpy(name,s.name)
return this shapeshape(const shape
s) name(new charstrlen(s.get_name())1)
strcpy(name,s.name) shapeshape()
delete name const char
shapeget_name() const return name
12
class rectangle public shape private
double a,b public rectangle(double,doubl
e) rectangle(const rectangle) rectangle
operator(const rectangle) virtual
rectangle() virtual double area() const
13
rectanglerectangle(double i, double
j) shape("rectangle"),a(i),b(j) rectangle
rectangleoperator(const rectangle r)
shapeoperator(r) a r.a b r.b
return this rectanglerectangle(const
rectangle r) shape(r) a r.a b r.b
rectanglerectangle() double
rectanglearea() const return ab
14
class circle public shape private double
r public circle(double) circle(const
circle) circle operator(const circle)
circle() double area() const
15
circlecircle(double i) shape("circle"),r(i)
circle circleoperator(const circle c)
shapeoperator(c) r c.r return this
circlecircle(const circle c)shape(c)
r c.r circlecircle() double
circlearea() const return 3.14159rr
16
const int L5 int main() shape shapes
new shapeL int i0 while (i lt L)
if() shapesi new circle(r)
else shapesi new
rectangle(a,b) i for(int i0 iltL,
i) cout ltlt shapesi-gtget_name() ltlt " with
area " ltlt shapesi-gtarea() ltlt endl delete
shapesi
17
Classes Abstraites
  • Une classe qui ne possède pas dinstance est
    dite abstraite. Cest forcément le cas si elle ne
    fournit pas d'implémentation pour certaines de
    ces méthodes. Ces méthodes seront alors appelées
    méthodes abstraites.
  • Ce sera les classes dérivées des classes
    abstraites qui auront une définition du code des
    méthodes abstraites. On pourra alors parler de
    classes concrètes les classes concrètes étant
    les seules à même dêtre instanciées.
  • Les classes abstraites définissent un cadre de
    travail pour les classes dérivées en proposant un
    ensemble de méthodes que l'on retrouvera tout au
    long de l'arborescence. Ce mécanisme est
    fondamental pour la mise en place du
    polymorphism.

18
Classes Abstraites
  • Pour certaines classes, il est tout à fait
    naturel de ne pas avoir d'instances un véhicule
    ne correspond à aucun objet concret mais plutôt
    au concept d'un objet capable de démarrer,
    ralentir, accélérer ou s'arrêter, que ce soit une
    voiture, un camion ou un avion.
  • Une classe ne peux être abstraite que si au
    moins une de ses méthodes virtuelles est pure.
    Pour déclarer une méthode virtuelle pure, il
    suffit de ne pas donner dimplantation et
    décrire
  • derrière sa déclaration. Seules les fonctions
    virtuelles peuvent être déclarées pures, sous
    peine derreur.

19
Classes Abstraites
class liste // classe abstraite protected
int nombre public virtual liste()
nombre 0 virtual void avance(int combien
1) 0 // pure void recule(int combien
1) avance(-combien) virtual
element valeur(void) 0 unsigned
nombre_elt(void) return nombre
void affiche(unsigned combien 65535)
virtual int insere(const element) 0
void supprime(int n 1) 0
  • Lorsquune classe est abstraite, elle ne peut
    être utilisée directement  en particulier, on ne
    peut pas déclarer dobjets de cette classe, ni
    darguments ou de résultats de fonction.
  • On peut par contre utiliser des références, des
    pointeurs et dériver de nouvelles classes, et
    cest en fait lusage de ces classes abstraites.

20
Classes Abstraites
class listech public liste // liste
chaînée noeud courant public listech()
nombre 0 courant 0
listech(int n, const element) listech()
void avance(int combien 1) element
valeur(void) if (courant) return
courant-gtcontenu() int insere(const
element) void supprime(int n 1)
21
Classes Abstraites
class listetab public liste element tab,
courant public listetab() courant
tab 0 listetab(int n, const element)
listetab() void avance(int combien 1)
element valeur(void) if (courant)
return courant int insere(const
element) void supprime(int n 1)
22
Classes Abstraites
  • La classe liste est abstraite, puisque quatre de
    ses méthodes ont été déclarées pures
  • Les classes abstraites nont généralement pas de
    constructeur, sauf si linitialisation des
    membres est un peu compliquée (ici il suffit de
    mettre la valeur adéquate dans le champ nombre,
    et les constructeurs de listch et listtab le
    font). Par contre, il est généralement
    souhaitable dy placer un destructeur virtuel,
    même sil ne fait rien comme dans notre exemple 
    on est ainsi certain de la bonne destruction des
    objets des classes dérivées.

23
Héritage Multiple
  • Il est parfaitement possible quune classe
    hérite de plusieurs classes. Voici un exemple 
  • La classe C hérite de manière publique de A et de
    manière privée de B (il faut préciser à chaque
    classe le type de dérivation, sinon cest le type
    par défaut qui sapplique). Elle a trois sortes
    de membres  les siens propres  ceux hérités de
    A  ceux hérités de B. Les règles dhéritage sont
    les mêmes que dans lhéritage simple.

class A // ... class B // ... class
C public A, B // ...
24
Héritage Multiple
  • Le constructeur de C appelle les constructeurs
    de A et B, implicitement ou non 
  • CC() A(), B() // ...
  • Noter que dans cette écriture, tout comme dans la
    déclaration dhéritage, cest une virgule qui
    sépare les différentes classes de base, et non le
    symbole deux-points.

25
Héritage Multiple
  • Lorsquune classe hérite de plusieurs autres, il
    se peut que deux des classes de base aient des
    champs ou des méthodes ayant le même nom.
  • Sil sagit dun champ dune part, et dune
    méthode dautre part, ou de deux méthodes mais
    avec des listes darguments différents, il ny a
    pas dambiguïté et le compilateur se débrouillera
    en fonction du contexte dutilisation.
  • Par contre, lorsquil sagit de deux champs, ou
    de deux classes A et B ont toutes deux un champ
    x, il faudra écrire 
  • C c
  • c.Ax 0

26
Héritage Multiple
  • Lorsquil sagit de méthodes, il est préférable
    de recouvrir les méthodes de base en déclarant
    une méthode dans la nouvelle classe ayant le même
    nom et les mêmes arguments.
  • Pour les méthodes ayant les mêmes arguments, le
    compilateur se trouve face à une ambiguïté
    insoluble. Pour la résoudre, il faut utiliser le
    nom dune des classes de base et lopérateur de
    résolution de portée.
Write a Comment
User Comments (0)
About PowerShow.com