Vous êtes sur la page 1sur 55

Université Cadi Ayyad

Ecole Supérieure de Technologie – Safi

Cours de programmation orientée objet


(C++)

Pr. SAID EL ABDELLAOUI


Elabdellaoui.said@yahoo.fr

Cours 2

Mohamed
El Nabil
Abdellaoui SaïdSaidi 2020 2021
Classe, Objet

2
Classe, Objet

 Avantages :
 rapproche les données et leur traitement: c'est l'objet qui sait le mieux comment gérer une
demande (lien sémantique )

 renforce la robustesse et la structure du programme

 simplifie la maintenance et la construction

 permet l'encapsulation : possibilité de ne montrer de l'objet que ce qui est

nécessaire à son utilisation (Private).

 permet de masquer l'implémentation (abstraction)

Mohamed
El Nabil
Abdellaoui SaïdSaidi 3
Classe, Objet : Exemple
 Exemple : Classe « Point » :

Description (Class, …) Instanciation (Objet : main)

Point

- x : int aa ba c
- y : int

+ SetPoint() : void x =? x =? x =?
y=? y=? y=?
+ Deplacer() : void
+ Afficher() : void

 Les attributs (données) x et y sont dites privées. Ceci signifie que l’on ne peut les manipuler qu’au
travers des fonctions membres (l’encapsulation des données).
 SetPoint() Deplacer() Afficher(); ce sont les méthodes appliqués sur les objets de type Point. On
l’appelle aussi des fonctions membres.
 a, b et c sont des objets de classe «Point», c’est-à-dire des variables de type «Point». On parle
aussi d ’instances.

Mohamed
El Nabil
Abdellaoui SaïdSaidi 4
Classe, Objet
 Déclaration d’une classe
 Syntaxe :
class NomClass{
//...
};

 Exemple :
class Rectangle {
private : double h;
double L;
//...
};

 Instanciation d’une classe :


NomClasse Nom_Instance; // le constructeur par défaut par défaut est appelé

Ceci définit un nouveau type du langage.


 Exemple :
Rectangle rect1; rect
a

h =?
L=?

Mohamed
El Nabil
Abdellaoui SaïdSaidi 5
Attributs

 La déclaration des attributs se fait comme suit :

 précéder par le modification :

 syntaxe
[ Modificateur ] : nomAttribut;

☞ Ce modificateur influence sur toute les lignes qui le suit jusqu’à la présence d’un autre,

 Exemple

private : int a;
double b;
double périmétre () {
// coprs
}
public : double surface () {
// coprs
}

☞ Les variables a, b et la méthode périmétre () sont privées contrairement à la méthode surface ()


qui est une méthode publique.

Mohamed
El Nabil
Abdellaoui SaïdSaidi 6
Méthodes
 La déclaration des méthodes suit deux façons :

 Interne : La déclaration des méthodes est à l’intérieure de la classe.

 Externe : : La déclaration des méthodes est à l’extérieure de la classe. Pour relier la définition d’une
méthode à sa classe, il suffit d’utiliser l’opérateur :: de résolution de portée.

1. la déclaration de la classe contient les prototypes des méthodes

[TypeRetour] nomFonction(type1, type2,…) ;

2. les définitions correspondantes spécifiées à l’extérieur de la déclaration de la classe se


font sous la forme :

[TypeRetour] NomClasse::nomFonction(type1 par1,type2 par2,…) {


//…
}

Mohamed
El Nabil
Abdellaoui SaïdSaidi 7
Principe de programmation
 L'encapsulation peut se pratiquer en donnant à l'utilisateur
 un fichier en-tête contenant la déclaration de la classe;
 un module objet contenant la version compilée du fichier contenant la définition de la classe.
 Il s'agit de ne montrer à l'utilisateur que ce qui lui est destiné compilée du fichier contenant la définition de
la classe. Dans la version plus élaborée:
 seules des fonction d'accès et de modification sont rendues publiques;
 toute donnée est privée ou protégée;

Exemple : Pour assurer une bonne encapsulation, on décompose notre programme comme suit :
 un fichier Point.h de déclaration de la classe Point
 un fichier Point.cpp d'implémentation des méthodes de la classe
 un fichier Demo_Point.cpp d'utilisation.
Point.h Point.cpp Demo_Point.cpp
#include <iostream>
ifndef POINT_H
#include "Point.cpp"
#define POINT_H #include "Point.h"
using namespace std;
class Point
void main() {
//Attribut et protopyes //Définitions de Méthodes
/* instanciation de
};
la classe */
#endif
}

Mohamed
El Nabil
Abdellaoui SaïdSaidi 8
Exemple : Encapsulation (déclaration interne)
Point.cpp

#include <iostream>
using namespace std;
class Point {
private : int x, y;
public:
Void setPoint(int a,int b){x=a;y=b;}

Void deplace (int dx,int dy){x +=dx;y+=dy;}

Void affiche(){cout<<"x="<< x <<",y="<< y <<endl;}

};

void main() {
Point a, b;
a.setPoint(1, 2); b.setPoint(3,-5);
a.affiche(); // x = 1, y = 2
a.deplace(1,1);
a.affiche(); // x = 2, y = 3
}

Mohamed
El Nabil
Abdellaoui SaïdSaidi 9
Exemple : Encapsulation (déclaration externe)
Point.cpp
#include <iostream>
using namespace std;
class Point {
private : int x, y;
public:
void setPoint (int, int);
void deplace (int, int);
void affiche();
};
void Point::setPoint(int a,int b){x=a;y=b;}

void Point::deplace (int dx,int dy){x +=dx;y+=dy;}

void Point::affiche(){cout<<"x="<< x <<",y="<< y


<<endl;}
};

void main() {
Point a, b;
a.setPoint(1, 2); b.setPoint(3,-5);
a.affiche(); // x = 1, y = 2
a.deplace(1,1);
a.affiche(); // x = 2, y = 3
}

Mohamed
El Nabil
Abdellaoui SaïdSaidi 10
Exemple : Encapsulation (Version améliorée)
#ifndef POINT_H
#define POINT_H
class Point {
private : int x, y;
Point.h

public:
void setPoint (int, int);
void deplace (int, int);
void affiche(); };
#endif

#include <iostream>
#include "Point.h"
Point.cpp

using namespace std;


void Point::setPoint(int a,int b){x=a;y=b;}
void Point::deplace (int dx,int dy){x +=dx;y+=dy;}
void Point::affiche(){cout<<"x="<<x<<",y="<<y<<endl;}

#include <iostream>
#include "Point.cpp"
Demo_Point.cpp

using namespace std;


void main() {
Point a, b;
a.setPoint(1, 2); b.setPoint(3,-5);
a.affiche(); // x = 1, y = 2
a.deplace(1,1);
a.affiche(); // x = 2, y = 3 }

Mohamed
El Nabil
Abdellaoui SaïdSaidi 11
Constructeur & Destructeur

12
Notion de Constructeur
 Le constructeur permet de d’ instancier une classe et initialiser les attributs.
 Propriétés d’un constructeur :
 porte toujours le même nom que la classe
 ne renvoie pas de valeur de retour (même pas un void)
 garantit que l ’objet sera toujours initialisé.

 Syntaxe :

NomClasse(liste_parametres) : liste des NomClasse(liste_parametres) {


ou
initialisations des parametres { //… } // liste des initialisations des parametres }

 Exemple :

Point(int a,int b){


Point(int a,int b) : x(a),y(b) { } ou x(a);y(b); //ou bien x=a; y=b;
}

 Un constructeur sans arguments est appelé constructeur par défaut.


 ce constructeur existe implicitement, s'il est le seul constructeur, on le nomme constructeur par
défaut par défaut. La définition d'un deuxième constructeur nous donne plus la possibilité de l’utiliser
sauf si l’on définisse explicitement
Mohamed
El Nabil
Abdellaoui SaïdSaidi 13
Constructeur par défaut par défaut

 Si aucun constructeur n’est spécifié, le compilateur génère automatiquement une version minimale
du constructeur par défaut par défaut qui :
 appelle le constructeur par défaut des attributs objets.
 laisse non initialisés les attributs de type de base.
 Dès qu’au moins un constructeur a été spécifié, ce constructeur par défaut par défaut n’est plus
fourni.
 Si donc on spécifie un constructeur sans spécifier de constructeur par défaut, on ne peut plus
construire d’objet de cette classe sans les initialiser (ce qui est voulu !) puisqu’il n’y a plus de
constructeur par défaut.
 On peut le rajouter si on veut :

NomClasse()= default;

Mohamed
El Nabil
Abdellaoui SaïdSaidi 14
Constructeur par défaut

 Constructeur par défaut : est un constructeur sans arguments ou dont chacun des arguments possède une
valeur par défaut. Il est utilisé lorsque l’on crée des tableaux d’objets.
 Exemple : class Toto {
private : int n;
public : Toto( int i); //constructeur}
};
void main(){
Toto tableau[3]; //Erreur : il faut un constructeur par défaut
getch() ;}

class Toto{ class Toto{


private : int n; private : int n;
public : Toto( int i=30); public : Toto() = default;
//constructeur par défaut} ; //constructeur par défaut}
}; };
void main() { void main() {
Toto tableau[3]; Toto tableau[3];
getch(); getch();
} }

Mohamed
El Nabil
Abdellaoui SaïdSaidi 15
Auto-référence : le pointeur this

 Si, dans une méthode, un attribut est masqué alors la valeur de l’attribut peut quand même être
référencée à l’aide du mot réservé this.

 this est un pointeur sur l’instance courante


this ~ "mon adresse"

 Syntaxe pour spécifier un attribut en cas d’ambiguïté :

this->nom_attribut

 Exemple :
class point {
int x,y
public :
void initialise(int , int);
};
void point :: initialise(int x, int y)
{this->x=x; this->y=y}

Mohamed
El Nabil
Abdellaoui SaïdSaidi 16
Notion de plusieurs constructeurs
#ifndef POINT_H
#define POINT_H
class Point {
Point.h

private : int x, y;
public: void setPoint (int, int);
void deplace (int, int);
void affiche(); };
#endif

#include <iostream.h>
#include "Point.h"
Point.cpp

Point::Point(){x=20;y=10;} // constructeur 1
Point::Point(int a,int b){x=a;y=b;} // constructeur 2
Point::Point(int a){x=a;y=30;} // constructeur 3
//affichage
//destructeur

#include <iostream>
#include "Point.h”
#include "Point.cpp"
Demo_Point.cpp

using namespace std;


main() {
Point a,b; // constructeur 1 : les objets ‘a’ et ‘b’ seront initialisé par 20, 10
Point c(1, 2); // constructeur 2 : l’objet ‘c’ est initialisé par 1, 2
Point d(3); // constructeur 3 : l’objet ‘d’ est initialisé par 3,30
a.affiche(); b.affiche(); c.affiche();
a.deplace(1,1); c.deplace(1,1);
a.affiche(); c.affiche(); }

Mohamed
El Nabil
Abdellaoui SaïdSaidi 17
Notion de constructeur pour les pointeurs
#ifndef POINT_H
#define POINT_H
class Point {
Point.h

private : int x, y;
public: void setPoint (int, int);
void deplace (int, int);
void affiche(); };
#endif

#include <iostream.h>
#include "Point.h«
Point.cpp

//affichage
Point::Point(int x, int y){this->x=x;this->y=y;}
//destructeur

#include <iostream>
#include "Point.h”
Demo_Point.cpp #include "Point.cpp"
using namespace std;
main() {
point *p;
p=new point(10,4);
p->afficher();
}

Mohamed
El Nabil
Abdellaoui SaïdSaidi 18
Notion de Destructeur
 Le destructeurs permet de spécifier ce qui doit être fait quand l'objet est désalloué. Ceci est important
quand un constructeur fait de l'allocation explicite.

 Propriétés d’un destructeur :


 porte le même nom que la classe
 est précédé par ~

 Syntaxe :
~ NomClasse() { //… }

class vecteur{
int taille,*v;
 Exemple :
public:
//constructeur
vecteur( int n) {if (n>0) taille = n; v=new int[n];}
//destructeur
~ vecteur() {delete v; cout<< "appel au destructeur"}
};

main(){ Vecteur Vect(2); }

 Remarque : pour un destructeur explicite on utilise la fonction suivante :


delete Obj;

Mohamed
El Nabil
Abdellaoui SaïdSaidi 19
Exemple : Constructeur
#ifndef POINT_H
#define POINT_H
class Point {
Point.h

private : int x, y;
public: Point (int, int);
void deplace (int, int);
void affiche (); };
#endif

#include <iostream>
#include "Point.h"
Point::Point(int a,int b):x(a),y(b){}
Point.cpp

void Point::deplace (int dx,int dy){x +=dx;y+=dy;}


void Point::affiche(){cout<<"x="<< x <<",y="<< y <<endl;}
Point::~Point (){cout<<"detruire("<<x<<","<<y<<")<<endl;}

#include <iostream>
Demo_Point.cpp

#include "Point.cpp"
using namespace std;
main() {
Point a(1, 2),b(3,-5);
a.affiche(); // x = 1, y = 2
a.deplace(1,1);
a.affiche(); // x = 2, y = 3 }

Mohamed
El Nabil
Abdellaoui SaïdSaidi 20
Méthodes (Action & Prédicat )
 En C++, on peut distinguer les méthodes qui modifient l’état de l’objet (« actions ») de celles qui ne
changent rien à l’objet (« prédicats »). On peut pour cela ajouter le mot const après la liste des paramètres de
la méthode :

[TypeRetour] nom_methode(type nom_par1,…) const


 Exemple :

class Rectangle{
double hauteur;
double largeur;
double surface() const ; // prototype
};
// définition
double Rectangle :: surface() const
{
return hauteur×largeur;
}

 Si vous déclarez une action en tant que prédicat (const), vous aurez à la compilation le message
d’erreur :

assignment of data-member ‘...’ in read-only structure

Mohamed
El Nabil
Abdellaoui SaïdSaidi 21
Accesseurs et manipulateurs
 Afin d’assurer l’encapsulation; il est préférable d’utiliser le modificateur d’accès private.
 Les membres privés ne sont accessibles que par les méthodes membres.

 Accesseurs (« méthodes get » ou « getters ») :


 Consultation (i.e. « prédicat »)

Retour de la valeur d’une variable d’instance précise.

double getHauteur() const {return hauteur; }

double getLargeur() const {return largeur; }

 Manipulateurs (« méthodes set » ou « setters ») :


 Modification (i.e. « action »)

Affectation de l’argument à une variable d’instance précise

void setHauteur (double h) {hauteur=h; }


void setLargeur (double l) {largeur=l; }

Mohamed
El Nabil
Abdellaoui SaïdSaidi 22
CONSTRUCTEUR
DE COPIE

23
CONSTRUCTEUR DE COPIE

 C++ offre un moyen de créer la copie d’une instance : le constructeur de copie

Rectangle r1(12.3 ,24.5);


Rectangle r2(r1);

=> r1 et r2 sont deux instances distinctes mais ayant des mêmes valeurs
pour leurs attributs.

 Ceci pose typiquement problème lorsque certains attributs de la classe sont des pointeurs.
 Examinons pourquoi sur un exemple concret...

Mohamed
El Nabil
Abdellaoui SaïdSaidi 24
CONSTRUCTEUR DE COPIE
 Soit une autre définition possible de classe Rectangle :
class Rectangle {
private:
double *largeur,*hauteur; // aîe, un pointeur !
public:
Rectangle(double l, double h) : largeur(new double(l)), hauteur(new double(h))
{}
~Rectangle() { delete largeur; delete hauteur; }
void afficher_largeur () { cout << "Largeur: " << * largeur<< endl; }
double getLargeur() const;
double getHauteur() const; // …
};

void main() {//……….


Rectangle r1(2.0,3.5),r2(r1);
r1.afficher_largeur (); r2.~Rectangle() ;
r1.afficher_largeur (); }...

Mohamed
El Nabil
Abdellaoui SaïdSaidi 25
EXEMPLE

Avant
r1
la copie Largeur

Hauteur

Après
r1 r2
la copie Largeur

Hauteur

Après la
destruction r1 r2
de tmp Largeur

Hauteur

☞ Il faut redéfinir le constructeur de copie de sorte à ce qu’il duplique véritablement les champs concernés → copie
profonde

Mohamed
El Nabil
Abdellaoui SaïdSaidi 26
CONSTRUCTEUR DE COPIE
 Solution :
class Rectangle {
private:
double *largeur,*hauteur; // aîe, un pointeur !
public:
Rectangle(double l, double h) : largeur(new double(l)), hauteur(new double(h))
{}
~Rectangle() { delete largeur; delete hauteur; }
void afficher_largeur () { cout << "Largeur: " << * largeur<< endl; }
double getLargeur() const;
double getHauteur() const; // …
};

void main() {//……….


Rectangle r1(2.0,3.5),r2(r1);
r1.afficher_largeur (); r2.~Rectangle() ;
r1.afficher_largeur (); }...

Mohamed
El Nabil
Abdellaoui SaïdSaidi 27
EXEMPLE

 Soit une autre définition possible de classe Rectangle :


class Rectangle {
private:
double *largeur,*hauteur; // aîe, un pointeur !
public:
Rectangle(double l, double h) : largeur(new double(l)), hauteur(new double(h)) {}
~Rectangle() { delete largeur; delete hauteur; }

double getLargeur() const;


double getHauteur() const; // …

void afficher_largeur (Rectangle tmp) {


cout << "Largeur: " << tmp.getLargeur() << endl; }
};

Question : Que se passe-t-il lorsqu’on invoque la fonction afficher_largeur(…) ?

void main() { Rectangle r (2.5,3);


afficher_largeur (r); //……… }...

Mohamed
El Nabil
Abdellaoui SaïdSaidi 28
EXEMPLE

void afficher_largeur (Rectangle tmp) { void main() {//……….


// une copie !.. Rectangle r;
cout <<"Largeur: "<<tmp.getLargeur()<< endl; } afficher_largeur (r); //………
// destruction de tmp... }...

 Lorsque afficher_largeur a fini de s’exécuter, l’objet tmp est automatiquement détruit par le
destructeur de la classe Rectangle
 Le destructeur va libérer la mémoire pointée par les champs largeur et hauteur de tmp.

☞ Attention ! cette portion de mémoire est aussi utilisée par r dans un appel comme
afficher_largeur(r) !
☞ Gros risque de segmentation Faut lors de la prochaine utilisation de r !!

Mohamed
El Nabil
Abdellaoui SaïdSaidi 29
EXEMPLE

Avant
r tmp
la copie Largeur

Hauteur

Après
r tmp
la copie Largeur

Hauteur

Après la
destruction r tmp
de tmp Largeur

Hauteur

☞ Il faut redéfinir le constructeur de copie de sorte à ce qu’il duplique véritablement les champs concernés → copie
profonde

Mohamed
El Nabil
Abdellaoui SaïdSaidi 30
SOLUTION

 Une bonne solution consiste alors à redéfinir le constructeur de copie :

Rectangle(const Rectangle& obj)


: largeur(new double(*(obj.largeur))),hauteur(new double(*(obj.hauteur)))
{ }

Avant
r tmp
la copie Largeur

Hauteur

Après la
destruction r tmp
de tmp Largeur Largeur

Hauteur Hauteur

Mohamed
El Nabil
Abdellaoui SaïdSaidi 31
EXEMPLE : DÉFINITION COMPLÈTE DE LA CLASSE

class Rectangle {
public:
Rectangle(double l, double h) : largeur(new double(l)), hauteur(new double(h)) {}
Rectangle(const Rectangle& );
~Rectangle();
// Note: il faudrait aussi redefinir operator= !
private: double *largeur, *hauteur;
};
// constructeur de copie
Rectangle:: Rectangle(const Rectangle& obj) : largeur(new double(*(obj.largeur))),
hauteur(new double(*(obj.hauteur)))
{ }
// destructeur
Rectangle::˜Rectangle() {delete largeur; delete hauteur;
}

☞ Il faudra aussi penser à redéfinir l’opérateur =

Mohamed
El Nabil
Abdellaoui SaïdSaidi 32
POUR CONCLURE

 Si une classe contient des pointeurs, penser à la copie profonde :


 constructeur de copie ;
 surcharge de l’opérateur = ;
 destructeur.
 Syntaxe :

NomClasse (NomClasse const& autre) { ... }

 Exemple :
Rectangle( Rectangle const& autre)
:hauteur(autre.hauteur), largeur(autre.largeur)
{}

 Par ailleurs, si l’on souhaite interdire la copie, il suffit de supprimer le constructeur de copie par défaut
avec la commande « = delete » vue dans la séquence précédente.

class PasCopiable{
/* ... */
PasCopiable (PasCopiable const&) = delete;
};

Mohamed
El Nabil
Abdellaoui SaïdSaidi 33
LES CONSTRUCTEURS EN C++ (RÉSUMÉ)
 Méthode constructeur(initialisation des attributs) :

NomClass(liste arguments) :
attribut1(...),
attributN(...)
{
// autres opérations
}

 Méthode constructeur de copie :

NomClasse(NomClasse const& obj) :...


{}

 Méthode destructeur(ne peut être surchargée) :

~NomClasse() {
// opérations de libération
}

 Des versions par défaut (minimales) de ces méthodes sont générées automatiquement par C++ si on ne
les fournit pas
 Règle : si on en définit une explicitement, il faut toutes les redéfinir !

Mohamed
El Nabil
Abdellaoui SaïdSaidi 34
LES TECHNIQUES
DE
L’HÉRITAGE

35
INTRODUCTION

Figure

Polygone Ellipse

Parallélogramme Triangle Cercle

Rectangle Triangle rectangle

Mohamed
El Nabil
Abdellaoui SaïdSaidi 36
PRINCIPES DE L’HÉRITAGE

 Le concept de l ’héritage constitue l’un des fondements de la P.O.O. Il a pour objectif de hiérarchiser
les classes et les objets.

 Il consiste à définir une nouvelle classe, appelée classe dérivée (ou classe Fille), à partir d ’une classe
existante appelée classe de base (classe mère).

Class mère Classe de base

Class fille Classe dérivée

 La classe dérivée hérite des potentialités de la classe de base, tout en lui en ajoutant de nouvelles.

Mohamed
El Nabil
Abdellaoui SaïdSaidi 37
PRINCIPES DE L’HÉRITAGE
 Une classe dérivée contient
 Attributs :
 les attributs de sa classe de base; Class de base

 peut en ajouter de nouvelles;

 Méthodes :
 possède a priori les méthodes de sa classe de base Class dérivée

(sauf les constructeurs/destr1cteurs);


 peut redéfinir (masquer) certaines méthodes;
 peut ajouter de nouvelles méthodes.

 Syntaxe de l ’héritage simple :

class NomSousClasse : [accès] NomSuperClasse


{
/* Déclaration des attributs et méthodes
spécifiques à la sous-classe */
};

 C++ autorise l ’héritage multiple dans lequel une classe peut être dérivée de plusieurs classes de base.

Mohamed
El Nabil
Abdellaoui SaïdSaidi 38
ACCÈS AUX MEMBRES

 L’accès aux membres (attributs et méthodes) d’une classe pouvait être :


 Public : visibilité totale à l’intérieur et à l’extérieur de la classe ( public)
 Privé : visibilité uniquement à l’intérieur de la classe (private)
 Protégé : assure la visibilité des membres d’une classe dans les classes de sa descendance (et
dans les autres classes du même paquetage) (protected).

 Récapitulatif des changements de niveaux d’accès aux membres hérités, en fonction du niveau
initial et du type d’héritage :

Accès initial
public Protected private
public public Protected Pas d’accès
Héritage

protected protected protected Pas d’accès


private private private Pas d’accès

 Le type d’héritage constitue une limite supérieure à la visibilité.

Mohamed
El Nabil
Abdellaoui SaïdSaidi 39
ACCÈS PROTÉGÉ

 Le niveau d’accès protégé correspond à une extension du niveau privé aux membres des sous-classes.
 Le niveau d’accès protégé correspond à une extension du niveau privé permettant l’accès aux sous-
classes… mais uniquement dans leur portée (de sous-classe), et non pas dans la portée de la super-classe

 Exemple 1 :

class Rectangle { main (){


public: Rectangle R1;
Rectangle(): largeur(1.0), hauteur(2.0) {} RectangleColore R2;
public : //afficher la largeur et la hauteur des
double largeur; double hauteur; objets
}; cout <<"la largeur est ="<<R2.largeur;
cout <<"la hauteur est ="<<R2. hauteur;
class RectangleColore : public Rectangle {
}
public: void carre() { largeur = hauteur; }
protected:
char couleur;
};

Mohamed
El Nabil
Abdellaoui SaïdSaidi 40
ACCÈS PROTÉGÉ

 Le niveau d’accès protégé correspond à une extension du niveau privé aux membres des sous-classes.
 Le niveau d’accès protégé correspond à une extension du niveau privé permettant l’accès aux sous-
classes… mais uniquement dans leur portée (de sous-classe), et non pas dans la portée de la super-classe

 Exemple 2 :

class Rectangle { main (){


public: Rectangle R1;
Rectangle(): largeur(1.0), hauteur(2.0) {} RectangleColore R2;
private : //afficher la largeur et la hauteur des
double largeur; double hauteur; objets
}; cout <<"la largeur est ="<<R2.largeur;
cout <<"la hauteur est ="<<R2. hauteur;
class RectangleColore : public Rectangle {
}
public: void carre() { largeur = hauteur; }
protected:
char couleur;
};

Mohamed
El Nabil
Abdellaoui SaïdSaidi 41
ACCÈS PROTÉGÉ

 Le niveau d’accès protégé correspond à une extension du niveau privé aux membres des sous-classes.
 Le niveau d’accès protégé correspond à une extension du niveau privé permettant l’accès aux sous-
classes… mais uniquement dans leur portée (de sous-classe), et non pas dans la portée de la super-classe

 Exemple 3 :

class Rectangle { class RectangleColore : public Rectangle {


public: public: void carre() { largeur = hauteur; }
Rectangle(): largeur(1.0), hauteur(2.0) {} private : char couleur; };
//Getters
main (){
double getlargeur() {return largeur;}
Rectangle R1; RectangleColore R2;
double gethateur() {return hauteur;}
//afficher la largeur et la hauteur
Protected:
cout <<"la largeur est ="<< R1.getlargeur();
double largeur; double hauteur;
cout <<"la hauteur est ="<< R1.gethauteur();
};
R2.carre();
cout <<"la largeur est ="<< R2.getlargeur();
cout <<"la hauteur est ="<< R2.gethauteur();
}

Mohamed
El Nabil
Abdellaoui SaïdSaidi 42
MASQUAGE & APPEL D’UNE MÉTHODE DE LA SUPER-CLASSE

 Exemple 2 :

class Rectangle { main (){


public: Rectangle R1;
Rectangle(): largeur(1.0), hauteur(2.0) {} RectangleColore R2;
//Getters R1.Affiche();
double getlargeur() {return largeur;} R2.Affiche();
double gethateur() {return hauteur;} }
void Affiche (){ class RectangleColore : public Rectangle
cout<<"la largeur est ="<< R1.getlargeur(); { public:
cout <<"la hauteur est ="<< R1.gethauteur(); void carre() { largeur = hauteur; }
}
Protected: void Affiche (){
double largeur; double hauteur;
Rectangle :: Affiche();
}; cout <<" la Couleur est "<<couleur;

Appel de la fonction }
de protected:
la class mère
char couleur; };

Mohamed
El Nabil
Abdellaoui SaïdSaidi 43
COMPOSITION OU HÉRITAGE
 Une classe est composée si certains de ses membres sont eux-mêmes des objets.
 La description d'un habitant fait partie d'une carte d'identité;
 correct car une carte d'identité n'est pas un cas particulier d'un habitant

class DescrHabitant { class Carte {


protected: DescrHabitant h;
string nom; int age;
string domicile; float age;
}; };

 La description d'un résident est plus complète que celle d'un habitant: l'information supplémentaire est
l'adresse de sa résidence (qui peut être différente de celle de son domicile).

class DescrResident : public DescrHabitant {


protected:
string residence;
};

 l’héritage doit être utilisé pour décrire une relation « est-un » ("is-a")
Attention
 il ne doit jamais décrire une relation « a-un »/« possède-un » ("has-a" )  Composition

Mohamed
El Nabil
Abdellaoui SaïdSaidi 44
EXEMPLES

 Exemple :
 Une voiture possède quatre (ou cinq) roues, donc
class Automobile {
Roue roues[5]; //…};

Un segment possède deux points;

class segment {
Point p1,p2; //Point points[2];
//… };

 Un anneau est un cas particulier d'un cercle;


class anneau : public cercle{
//…
};

 Un triangle est une forme particulière:

class Triangle : public Shape {


//…
};

Mohamed
El Nabil
Abdellaoui SaïdSaidi 45
CONSTRUCTEURS & HÉRITAGE

46
CONSTRUCTEURS PAR DÉFAUT & HÉRITAGE

 Comment invoquer un constructeur ????


class DescrHabitant { DescrHabitant::DescrHabitant() {
string nom ; cout << "Entrez votre nom : " ; cin >> nom ;
string domicile; cout << "Entrez votre domicile : " ; cin >> domicile ;}
public: DescrHabitant(); void DescrHabitant::show() {
void show(); cout << "Nom: \t\t" << nom << endl ;
}; cout << "Domicile \t" << domicile << endl;}

class DescrResidence : public DescrHabitant {


string residence;
public: DescrResidence();
void show();
};

DescrResidence::DescrResidence() {
// appel implicite du constructeur par défaut de la classe de base.
cout << "Entrez votre residence : " ; cin >> residence; }
void DescrResidence::show() {
DescrHabitant::show() ; // l'appel de la méthode de la classe de base.
cout << "Residence \t" << residence << endl ; }

Mohamed
El Nabil
Abdellaoui SaïdSaidi 47
CONSTRUCTEURS PAR DÉFAUT & HÉRITAGE

 Rappel : un constructeur par défaut c’est un constructeur sans paramètres :


 Comment invoquer un constructeur ???? Entrez votre nom : Dupont
void main() { Entrez votre domicile : Paris
DescrHabitant pierre; Nom: Dupont
pierre.show(); Domicile Paris
Entrez votre nom : Duval
DescrResidence paul; Entrez votre domicile : Marne
paul.show(); Entrez votre residence : Champs
Nom: Duval
pierre = paul; Domicile Marne
pierre.show(); Residence Champs
} Nom: Duval
Domicile Marne
 Le principe de substitution :
 Le principe de substitution s'énonce comme suit: toute occurrence d'un objet de la classe de base peut
toujours être remplacée par un objet d'une classe dérivée.
 Ici l'opérateur d'affectation prend un DescrHabitant en second paramètre.

Mohamed
El Nabil
Abdellaoui SaïdSaidi 48
CONSTRUCTEURS & HÉRITAGE

 L’invocation du constructeur de la super-classe se fait au début la section d’appel au constructeurs des


attributs.
 Syntaxe :

SousClasse (liste de paramétres) : SuperClasse(Arguments)


{
attribut1(valeur1);
...
attributN(valeurN);
// corps du constructeur
}

 Lorsque la super-classe admet un constructeur par défaut, l’invocation explicite de ce constructeur dans la
sous-classe n’est pas obligatoire
☞ le compilateur se charge de réaliser l’invocation du constructeur par défaut

Mohamed
El Nabil
Abdellaoui SaïdSaidi 49
CONSTRUCTEURS & HÉRITAGE

 Exemple :

class Rectangle {
protected: double largeur; double hauteur;
public: Class Rectangle
Rectangle(double l, double h) : largeur(l), hauteur(h){} largeur
// le reste de la classe... hauteur
};

class Rectangle3D : public Rectangle { Class Rectangle3D


protected: double profondeur;
profondeur
public:
Rectangle3D(double l, double h, double p)
: Rectangle(l,h), profondeur(p) {}
// le reste de la classe...
};

Mohamed
El Nabil
Abdellaoui SaïdSaidi 50
CONSTRUCTEURS & HÉRITAGE
 Autre exemple (qui ne fait pas la même chose) :

class Rectangle {
protected: double largeur; double hauteur;
public:
Rectangle() : largeur(0.0), hauteur(0.0){}
// constructeur par défaut
// le reste de la classe...
};

class Rectangle3D : public Rectangle {


protected: double profondeur;
public:
Rectangle3D(double p)
: profondeur(p) {}
// le reste de la classe...
};

 Ici il n’est pas nécessaire d’invoquer explicitement le constructeur de la classe parente puisque celle-ci
admet un constructeur par défaut.

Mohamed
El Nabil
Abdellaoui SaïdSaidi 51
HÉRITAGE & CONSTRUCTEUR DE COPIE

 Le constructeur de copie d’une sous-classe doit invoquer explicitement le constructeur de copie de la


super-classe
☞ Sinon c’est le constructeur par défaut de la super-classe qui est appelé !

 Exemple :

Rectangle ( Rectangle const& autre)


:FigureGeometrique (autre),
largeur(autre.largeur),
hauteur(autre.hauteur)
{}

Mohamed
El Nabil
Abdellaoui SaïdSaidi 52
HÉRITAGE & CONSTRUCTEURS
 Les constructeurs ne sont, en général, pas hérités
Mais en C++11 on peut demander leur héritage en utilisant le mot clé « using » . On récupère alors
tous les constructeurs de la super-classe, i.e. on peut construire la sous-classe avec les mêmes arguments,
mais...
☞ Attention ! ces constructeurs n’initialisent donc pas les attributs spécifiques de la sous-classe.
☞ C’est donc très risqué, et je vous conseille de ne l’utiliser que pour des sous-classes n’ayant pas de
nouvel attribut (et si c’est approprié) !

class A{ class B : public A{


public: using A::A;
A (int); /* existent alors maintenant
A (double,double); B::B(int)
// ... et B::B(double, double) */
}; };

Mohamed
El Nabil
Abdellaoui SaïdSaidi 53
HÉRITAGE (RÉCUP)
 Spécifier un lien d’héritage :

class Sousclasse : [public] SuperClass {...}

 Droits d’accès : protected accès autorisé au sein de la hiérarchie


 Masquage : un attribut/méthode peut être redéfini dans une sous-classe

 Accès à un membre caché :

SuperClasse::membre

 Le constructeur d’une sous classe doit faire appel au constructeur de la super classe :

class SousClasse: SuperClasse


{
SousClasse(liste de paramétres)
: SuperClasse(Arguments),attribut1(valeur1), ..., attributN(valeurN) {...}
};

Mohamed
El Nabil
Abdellaoui SaïdSaidi 54

Vous aimerez peut-être aussi