Vous êtes sur la page 1sur 30

CHAPITRE 5

LA TECHNIQUE DE L’HERITAGE

Le principe de l’héritage est un concept fondamental dans la programmation


orientée objet. Il permet de définir une nouvelle classe (dite dérivée),
à partir d’une classe existante (dite de base)

5. 1 Mise en œuvre

class <classe derivée> : public <classe de base>


{
private:

public:
..
}

1
Exemple:
soit point la classe de base:
classe point
{
private:
int x;
int y;
public:
void init(int x,int y)
{
this->x=x;this->y=y;
}
void view()
{
cout <<x<<y;
}
}

classe pointcol :public point


{
private:
int couleur;
public:
void colorer(int couleur)
{
this->couleur=couleur;
}
void view_col()
{
view();
cout << couleur;
}
}
2
L’expression :public point signifie que les membres publics de la classe de base point
seront des membres publics de la classe dérivée point.

soit la fonction main suivante:


void main()
{
pointcol p;

p.init(10,20);
p.color(7);
p.view();
p.view_col();
}

ici p est un objet de la classe dérivée pointcol. On peut appeler les méthodes
publics de sa classe (p.color(7) et p.vew_col() ) ainsi que les méthodes publics
de sa classe de base (p.init(10,20) et p.view() ).

3
5.2 Utilisation dans une classe dérivée des membres de la classe de base.

Une classe dérivée n’a pas d’accès aux membres privés de sa classe de base.
Exemple:
class pointcol :public point
{
private:
int couleur;
public:

void view_col()
{
cout << x<<y; // La solution :appeler view() la méthode publique
// de la classe de base qui affiche x et y.
//x et y étant des membres privés de la classe de base point
//donc inaccessible par la classe dérivée.
cout << couleur;
}
}

4
5.3 Redéfinition des fonctions membres

La méthode d’affichage de la classe dérivée aurait pu être appelée view tout comme
celle de la classe de base.
class pointcol :public point
{
private:
int couleur;
public:
void colorer(int couleur)
{
this->couleur=couleur;
}
void view()
{
point::view();
cout << couleur;
}
}
5
Remarque:
Il est possible d’avoir les mêmes noms pour les membres de données.

Exemple:
class A class B:public A
{ {
public : private:
int a; float a;
char c; public:
… void test()
} {
B b;
cout << a; // a de la classe B
cout <<A::a; // a de la classe A
}
}

6
5.4 Appel des constructeurs et destructeurs

Soit la déclaration:

B b; // b un objet de la classe dérivée B

Ceci se traduit par :

•Création d’un objet de type A


•Appel du constructeur de A
•Compléter ce qui est spécifique à B
•Faire appel au constructeur de B

La destruction conduit à:
•Appel au destructeur de B
•Appel au destructeur de A

7
5.5 Transmission d’informations entre constructeurs

Si la classe de base d’un constructeur avec paramètres, la classe dérivée doit avoir
un constructeur et la transmission d’informations de fait comme cet exemple:
class pointcol :public point
{
private:
int couleur;
public:
pointcol(int x, int y, int couleur) : point(x,y)
{
this->couleur=couleur;
}
}
:point(x,y) signifie que le constructeur de pointcol devra transmettre au
constructeur de la classe point , dans l’ordre, x et y.

8
5.6 Constructeur par Recopie

Soit la déclaration
B b2=b1;

Si la classe B a défini un constructeur par recopie, il n’y a pas appel automatique


d’un constructeur par recopie de la classe de base. Cela signinfie donc que
le constructeur par recopie de la classe dérivée doit prendre en charge l’intégralité
de l’objet et non seulement de sa partie spécifique.
Class A class B:public A
{ {
.. …

A(const A&p) B(const B&t)


{ {
} //ce constructeur doit prendre en charge
} //sa partie spécifique et celle de la classe
//de base, pas d’appel au const par recopie
// de A
}
9
}
5.7 Les membres protégés

Aux mots clés public et private s’ajoute le mot clé protected qui permet de
considérer un membre privé mais accessible à une classe dérivée.

Exemple:
class point
{
protected:
int x;
int y;
public:

}

class pointcol :public point


{
private:
int couleur;
void view()
{
cout << x<<y ; // Juste parce que x et y sont des membres protégés de la classe de base don accessibles ici
cout <<couleur;
}
}

10
5.8 Différentes formes de dérivation

•Dérivation publique

Les membres publics de la classe de base sont accessibles à toutes les fonctions c.a.d:
 Aux fonctions membres de la classe dérivée
 Aux fonctions membres amies de la classe dérivée
 Aux utilisateurs de la classe dérivée.

Les membres protégés de la classe de base sont accessibles aux:


Fonctions membres de la classe dérivée
Fonctions amies de la classe dérivée
Mais pas accessibles aux utilisateurs de la classe dérivée.

Les membres privés de la classe de base sont inaccessibles aux fonctions membres
de la classe dérivée , amies, utilisateurs de la classe dérivée.

11
•Dérivation privée
Il est possible d’interdire à un utilisateur d’une classe dérivée l’accès aux membres
publics de sa classe de base.
On utilisera dans ce cas le mot clé private au lieu du mot clé public.
Exemple
Class point classe pointcol :private point
{ {
private: private:
int x; int couleur;
int y; public:
public: void colore(int couleur)
.. {
void deplace(int a,int b) this->couleur=couleur;
{ }
} }
}
main()
{
pointcol p;
p.deplace(3,10); //p est un objet de pointcol qui fait une dérivation privée donc
p.color(7); // impossible pour main (une fonction utilisatrice de pointcol)
// D’accèder aux la fonction membre public deplace()
} 12
•Dérivation protégée

Intermédiaire entre dérivation publique et dérivation privée.


Dans ce cas, les membres publics de la classe de base seront considérés comme
protégés lors des dérivations ultérieures. (un membre public de la classe de base n’est
donc accessible que par les méthodes de la classe dérivée parce qu’il s’agit d’une
dérivation protégée.
Exemple
class A class B:protected A
{ {
public: public :
void go() void test()
{ {
go(); // Correct
} }
}
void main()
{
B b;
b.test();
b.A::go(); // Incorrect parce que go() est protected, elle est considérée privée
} // pour main 13
5.9 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 remplacer un objet d’une classe de base, étant donnée
qu’il y a toujours dans l’objet de la classe dérivée les données de la classe de base ainsi que
l’accès aux fonctions membres.

Cette compatibilité se résume à l’existence de conversions implicites


 d’un objet d’un type dérivé dans un objet d’un type de base
 d’un pointeur sur une classe dérivée en un pointeur sur une classe de base

•Conversion d’un objet dérivé dans un objet d’un type de base


Exemple:
point a;
pointcol b;
l’affectation suivante est légale
a=b;
Elle entraine une conversion de b en type point et l’affectation du résultat dans a.
Cette affectation se fait suivant le cas:
 Par appel à l’opérateur d’affectation de point s’il a été surdéfini
 Par emplois de l’affectation par défaut dans le cas contraire.
L’affectation b= a; sera rejetée.
14
•Conversion d’un pointeur sur une classe dérivée en pointeur sur une classe de base

Soit les déclarations suivantes:


point *adp;
pointcol *adpc;

Le C++ autorise l’affectation


adp=adpc;
Qui correspond à une conversion du type pointcol * dans un type point *

15
5.10 Opérateur d’affectation et héritage

Soit la déclaration
class B:public A
{
}

•Cas où la classe B n’a pas surdéfinie l’opérateur =

Soit B p1,p2;
L’affectation p1=p2;
Se déroule membre par membre en considérant que la partie héritée de A constitue un
membre. La partie héritée de A est traitée par l’affectation prévue (s’il y a une surdéfinition de
l’opérateur = il sera appelé.

Cas où la classe dérivée B a surdéfini l’opérateur =


Soit B p1,p2;
L’affectation p1=p2;
Fait appel à l’opérateur = défini dans B, celui de A ne sera pas appelé même s’il a été surdéfini.

16
Exemple:

Class point
{
protected :
int x;
int y;
public:
point(int a=0,int b=0) {x=a;y=b;}
point & operator=(point &a)
{
x=a.x;y=a.y;return(*this);
}
}
Class pointcol
{
protected:
int couleur;
public:
pointcol(int a=0,int b=0,int c=1) :point(a,b) {couleur=c;}
pointcol & operator=(point &b)
{
Couleur=b.coluleur; //Ne Suffit pas pour l’affectation
17
}
5.11 HERITAGE MULTIPLE

Une classe peut hériter de 2 classes de base. La classe dérivée va donc hériter des
fonctionnalités des 2 classes de base. Ainsi, on parle dans ce cas d’héritage multiple.

Déclaration :
class <classe derivée> : public <classe de base1>, public <classe base 2>
{
private:

public:
..
}

18
Exemple d’illustration
class point class col
{ {
private : private:
int x; int couleur;
int y;
public: public:
point(int x,int y) col(int couleur)
{ {
this->x=x; this->couleur=couleur;
this->y=y; }
}
.. …
} }

class pointcol :public point,public col


{
public:
pointcol(int x,int y,int couleur) point(x,y),col(couleur)
{
}

}
19
Remarque:

 L’ordre d’appel des constructeurs est le suivant:

• Constructeur des classes de base, dans l’ordre où les classes de bases sont
déclarées dans la classe dérivée.
• Constructeur de la classe dérivée.

 Les destructeurs sont appelés dans l’ordre inverse lors de la destruction d’un objet
de type pointcol (col ensuite point)

 Plusieurs fonctions membres peuvent porter le même nom dans différentes classes.
On peut lever l’ambiguité en employant l’opérateur de résolution de portée ::
Exemple

class pointcol :public point,public col


{
void view()
{
point::view();
col::view();
}
} 20
5.12 Les classe virtuelles

Considérons la situation suivante:


class A
{
A
int x;
int y;
}
Class B : public A B C
Class C : public A
Class D :public B,public C

D Hérite 2 fois de A
Les données de A vont apparaitre 2 fois dans D. D
En général, on ne souhaite pas cette duplication des données.
Solution: déclaration virtuelle:
Class B : public virtual A A ne devra introduite qu’une seule fois
Class C : public virtual A au niveau héritage.
Class D :public B,public C
21
5.13 Conflit de nom entre classe de base et classe dérivée lors de l’utilisation
des pointeurs

Soit les définitions suivantes:

class A class B:public A


{ {
public : void view()
void view() {
{ cout << Classe dérivée »;
cout << « Classe de Base »; }
}
} }
void main()
{
A*p=new A;
p->view(); // Classe de Base
p=new B;
p->view(); // Classe de base !! Alors que p a été initialisé sur un objet de B
}
SOLUTION : Utiliser des méthodes virtuelles.
22
class A class B:public A
{ {
public : public:
virtual void view() virtual void view() {
{ { cout << Classe dérivée »;
cout << « Classe de Base »; }
}
} }
void main()
{
A*p=new A;
p->view(); // Classe de Base
p=new B;
p->view(); // Classe dérivée
}

23
5.14 Polymorphisme

Le polymorphisme décrit la capacité d’un objet de prendre plusieurs formes.


En C++ le polymorphisme est possible à travers l’utilsation des méthodes virtuelles.
Lorsqu’on utilise un pointeur, le même pointeur peut pointer sur différentes classes.

Exemple

class Base
{
public : void main()
virtual int ajouter (int a, int b) {return(a+b);} {
virtual int soustraire(int a, int b) {return(a -b);} Base *p=new Math;
virtual int multiplier (inta, int b) {return(a*b);} cout << p->ajouter(10,20)<<p->soustraire(40,10);
} p->multiplier(10,3);
class Math : public Base p=new Absolue;
{ cout << p-ajouter(15,15<<p->soustraire(10,40);
public: cout <<multiplier(1,30);
virtual int multiplier(int a int b) {cout <<a*b<<‘\n’; return(a*b);] }
}
classe Absolue:public Base
{
public:
virtual int sustraire (int a,int b) { return(abs(a-b));}
}

24
5.15 Méthode virtuelle pure
Une méthode virtuelle pure correspond à un protocole déclaré dans la classe de
base et pour lequel la classe dérivée doit fournir une implémentation.
Dans une classe, une méthode virtuelle pure doit être déclarée comme suit:

virtual <prototype de la fonction> =0;


Exemple
class A
{
public :
virtual void view() { cout << « classe de Base »;}
virtual void view_inverse()=0;
}
class B:public A
{
public:
virtual void view(){ cout << « Classe dérivée »;}
virtual void view_inverse(){ cout << inv(« Classe Dérivée « );}
}
void main()
{
A*p=new B;
p->view();
p-view_inverse();
}

25
5.16 Classe Abstraite

Lorsqu’une classe contient uniquement des méthodes virtuelles pures, C++ la


considère comme étant une classe abstraite.
Class Bidon
{
public :
void f1()=0;
int f2(int, int, float)=0;
void f3()=0;
}
Bidon est une classe abstraite.

26
15.17 Affecter une classe à une autre

Il est possible d’affecter un objet d’une classe à un autre objet d’une autre classe.
Une conversion est dans ce cas nécessaire.

Exemple
void main()
{
point a;
char *s;
s=a;
cout <<s;
}
Dans ce cas il faut définir l’opérateur char *
pour la conversion d’un objet de la classe point. point::operator char *()
{
class point char *p=new char [256];
{ sprintf(p, »X:%d Y:%d »,x,y);
.. return(p);
operator char *(void); }
}
27
28
29
30

Vous aimerez peut-être aussi