Vous êtes sur la page 1sur 57

INF3034

Programmation Orientée Objet


Aurélien Texier
texier@esiea.fr
2021-2022
POO - Les concepts
Introduction

INF3034 – Programmation orientée objet 2


Programmation Orientée Objet
 Paradigme de programmation informatique créée autour des années 60-70.
 Définition de briques logicielles appelées Objets.
 Un objet peut représenter un concept, une idée ou une entité physique.
 Un objet est composé de :
 Différents éléments qui le constituent ;
 Différentes fonctions associées aux éléments.
 Pour identifier les composants d’un objet, une méthode consiste à décrire l’objet
de manière littérale.
 Les noms communs donnent les éléments ;
 Les verbes donnent les fonctions.

INF3034 – Programmation orientée objet 3


Programmation Orientée Objet
 Exemple : Un chronomètre digital
« Ce chronomètre comporte un temps qui s’affiche et deux boutons A et B. Quand
on appuie sur A, on lance le chronomètre ou on l’arrête. Quand on appuie sur B,
on remet à zéro le chronomètre. »

nom : chronometre
éléments : fonctions :
bouton A afficher
bouton B appuyer sur un bouton
temps lancer
arrêter
remettre à zéro

INF3034 – Programmation orientée objet 4


Programmation Orientée Objet
 Plusieurs langages utilisent ce paradigme
 C++, Java, C#, …
 Le langage C++
 Apparu en 1983 (11 ans après le langage C)
 Est une "évolution" du langage C (d’où le ++)
 Très utilisé (notamment en Réalité Virtuelle et en jeux vidéo)
 Ne comporte pas de Garbage Collector gérant la mémoire automatiquement
(comme le Java ou le C#).

INF3034 – Programmation orientée objet 5


POO – Classe
 En POO, un objet est une structure informatique comportant :
 Des variables, appelées membres ;
 Des fonctions appelées méthodes.
 Un ensemble d’objets de même type est une classe.
 Exemple :
 Imaginons que l’on dispose de plusieurs chronomètres, ils appartiennent tous à la
classe "chronomètre", chacun d’eux étant une instance de la classe.
 En décrivant la classe, on décrit l’ensemble des objets de cette classe.
 La description se fait en deux parties :
 La déclaration descriptif des membres et méthodes composant la classe.
 La définition programmation des méthodes de la classe.
INF3034 – Programmation orientée objet 6
POO – Classe
 En C++
Déclaration :

1 class CChronometer chronometer.h


2 {
3 // Membres de la classe
4 float m_time; /**< time of the chronometer */
5 int m_buttonA; /**< Button A of the chronometer */
6 int m_buttonB; /**< Button B of the chronometer */
7
8 // Méthodes de la classe
9 int PushButton(int p_button);
10 void Begin();
11 void End();
12 void Reset();
13 void PrintTime();
14 };

INF3034 – Programmation orientée objet 7


POO – Classe
 En C++
Définition :

1 #include "chronometer.h" chronometer.cpp


2
3 void CChronometer::Reset()
4 {
5 m_time = 0.0f;
6 }
7
8 void CChronometer::PrintTime()
9 {
10 printf("%f\n", m_time);
11 }
12
13 ...
14

INF3034 – Programmation orientée objet 8


POO – Classe
 En C++
Utilisation :

1 #include "chronometer.h" main.cpp


2
3 int main(int argc, char **argv)
4 {
5 // Création/Instantiation d’un objet chrono
6 // de type CChronometer
7 CChronometer chrono;
8
9 // Accès au membre m_time
10 chrono.m_time = 21.0f;
11
12 // Appel de la méthode Reset()
13 chrono.Reset();
14 }

INF3034 – Programmation orientée objet 9


POO - Les concepts
Constructeurs

INF3034 – Programmation orientée objet 10


POO – Constructeur / Destructeur
 En POO, une fonction particulière est appelée lors de l’instanciation.
 Le constructeur
 Fonction permettant l’allocation mémoire nécessaire ainsi que l’initialisation
des variables membres.
 Cette fonction a pour nom le nom de la classe et n’a pas de type de retour
 CChronometer();

INF3034 – Programmation orientée objet 11


POO – Constructeur / Destructeur
 Il existe aussi une fonction spéciale qui permet de libérer les ressources alloué
dynamiquement lors de la destruction de l’objet.
 Le destructeur
 N’a d’utilité que dans des langages n’utilisant pas de Garbage Collector.
 ~CChronometer();

INF3034 – Programmation orientée objet 12


POO – Constructeur / Destructeur
 En C++
Déclaration :

1 class CChronometer { chronometer.h


2 // Membres de la classe
3 ...
4
5 // Constructeurs
6 CChronometer();
7
8 // Destructeurs
9 ~CChronometer();
10
11 // Autres méthodes
12 ...
13
14 };

INF3034 – Programmation orientée objet 13


POO – Constructeur / Destructeur
 En C++
Déclaration :

1 // Constructeur
class CChronometer { chronometer.cpp
chronometer.h
2 CChronometer::CChronometer()
// Membres de la classe
3 { ...
4 m_time = 0.0f;
5 // Constructeurs
m_buttonA = 0;
6 CChronometer();
m_buttonB = 0;
7 }
8 // Destructeurs
9 // Destructeur
~CChronometer();
10 CChronometer::~CChronometer()
11 { // Autres méthodes
12 ...
13 }
14 };

INF3034 – Programmation orientée objet 14


POO – Constructeur / Destructeur
 En C++
 Le C++ permettant la surcharge, il est possible d’avoir plusieurs constructeurs pour une
même classe.
 On distingue plusieurs types de constructeurs :
 Constructeur par défaut : ne possède aucun argument ;
 Constructeur paramétrique : possède plusieurs arguments permettant l’initialisation.

 A contrario, il ne peut y avoir qu’un seul destructeur.

INF3034 – Programmation orientée objet 15


POO – Constructeur / Destructeur
 En C++
Déclaration :

1 class CChronometer { chronometer.h


2 // Membres de la classe
3 ...
4
5 // Constructeurs
6 CChronometer();
7 CChronometer(float p_time);
8
9 // Destructeurs
10 ~CChronometer();
11
12 // Autres méthodes
13 ...
14 };

INF3034 – Programmation orientée objet 16


POO – Constructeur / Destructeur
 En C++
 De plus, possibilité d’utiliser la syntaxe constructeur(argument) : membre(argument)
pour initialiser directement les variables.

INF3034 – Programmation orientée objet 17


POO – Constructeur / Destructeur
 En C++
Définition :

1 // Constructeur paramétrique chronometer.cpp


2 CChronometer::CChronometer(float p_time):
3 m_time(p_time),
4 m_buttonA(0)
5 {
6 m_buttonB = 0;
7 }
8
9 // Destructeur
10 CChronometer::~CChronometer()
11 {
12
13 }
14

INF3034 – Programmation orientée objet 18


POO – Constructeur / Destructeur
 En C++
Utilisation :

1 #include "chronometer.h" main.cpp


2
3 int main(int argc, char **argv)
4 {
5 CChronometer chrono1; // Appel au constructeur par défaut pour chrono1
6 CChronometer chrono2(73,0f); // Appel au constructeur par paramétrique pour chrono2
7
8 chrono1.m_time = 21.0f; // Modification du membre m_time de chrono1
9 chrono1.Reset(); // Appel de la méthode Reset de chrono1
10
11
12
13 } // Appel aux destructeurs de chrono1 et chrono2
14

INF3034 – Programmation orientée objet 19


POO – Constructeur / Destructeur
 En C++
 Dans le cas de l’utilisation d’un pointeur sur l’objet, il faut utiliser le mot-clé new
pour appeler le constructeur.
 Cela alloue l’espace mémoire et appelle le constructeur
 De même, il faut appeler le mot clé delete pour le libérer.

INF3034 – Programmation orientée objet 20


POO – Constructeur / Destructeur
 En C++
Utilisation :

1 #include "chronometer.h" main.cpp


2
3 int main(int argc, char **argv)
4 {
5 CChronometer chrono1, chrono2; // Appel des constructeurs pour chrono1 et chrono2
6
7 CChronometer *pChrono;
8 pChrono = new CChronometer(73.0f); // Appel au constructeur paramétrique pour pChrono
9
10 pChrono->m_time = 21,0f; // Modification du membre m_time de pChrono
11 pChrono->Reset(); // Appel de la méthode reset de pChrono
12
13 delete pChrono; // Appel au destructeurs de pChrono
14 } // Appel aux destructeurs de chrono1 et chrono2

INF3034 – Programmation orientée objet 21


C++ - Notions
Passage par référence

INF3034 – Programmation orientée objet 22


C++ – Passage par référence
 En C++ possibilité de faire du passage par adresse sans pointeurs.
 Passage par référence
 Utilisation de & pour indiquer une référence.
 Exemple :
1 void increment_ptr(int *p_pi)
2 {
3 (*p_pi)++;
4 }
5
6 int main(int argc, char **argv)
7 {
8 int a=6; // a vaut 6
9 increment_ptr(&a); // a vaut maintenant 7
10 }

INF3034 – Programmation orientée objet 23


C++ – Passage par référence
 En C++ possibilité de faire du passage par adresse sans pointeurs.
 Passage par référence
 Utilisation de & pour indiquer une référence.
 Exemple :
1 void increment_ref(int &p_ri)
2 {
3 p_ri++;
4 }
5
6 int main(int argc, char **argv)
7 {
8 int a=6; // a vaut 6
9 increment_ref(a); // a vaut maintenant 7
10 }

INF3034 – Programmation orientée objet 24


POO – Constructeur / Destructeur
 En C++
 Le C++ permettant la surcharge, il est possible d’avoir plusieurs constructeurs pour
une même classe.
 On distingue plusieurs types de constructeurs :
 Constructeur par défaut : ne possède aucun argument ;
 Constructeur paramétrique : possède plusieurs arguments permettant
l’initialisation.
 Constructeur par copie : possède un unique argument du type de
l’objet à créer.
 A contrario, il ne peut y avoir qu’un seul destructeur.

INF3034 – Programmation orientée objet 25


C++ – Passage par référence
 En C++
Déclaration :

1 class CChronometer { chronometer.h


2 // Membres de la classe
3 ...
4
5 // Constructeurs
6 CChronometer();
7 CChronometer(float p_time);
8 CChronometer(const CChronometer& p_chrono);
9 // Destructeurs
10 ~CChronometer();
11
12 // Autres méthodes
13 ...
14 };

INF3034 – Programmation orientée objet 26


C++ – Passage par référence
 L’autre conséquence du passage par référence est que l’objet passé en
paramètre n’est pas une copie. C’est l’objet.
 Pas d’appel au constructeur par copie.
 Pas de "code caché"

 Utilisation du mot-clé const pour éviter la modification.

INF3034 – Programmation orientée objet 27


POO - Les concepts
L’encapsulation

INF3034 – Programmation orientée objet 28


POO – Encapsulation
 Possibilité de donner accès ou non aux variables membres et méthodes depuis
l’extérieur.
 L’encapsulation
 Exemple : l’utilisateur du chronomètre ne doit pas avoir accès à la variable
m_time directement. Il doit passer par les méthodes printTime() ou begin()
par exemple.
 Notion de composants privés ou publiques.
 En règle général, les membres sont privés
 Utilisation de getter / setter.

INF3034 – Programmation orientée objet 29


POO – Encapsulation
 En C++
Déclaration :

1 class CObject object.h


2 {
3 private:
4 // Membres de la classe
5 int m_index;
6
7 public:
8 // Méthodes de la classe
9 CObject();
10 ~CObject();
11
12 // Setter de la variable membre m_index
13 void SetIndex(int p_index);
14 // Getter de la variable membre m_index
15 int GetIndex();
16 }
INF3034 – Programmation orientée objet 30
POO – Encapsulation
 En C++
Définition :

1 object.cpp
2
3 // Setter de la variable membre m_index
4 void CObject::SetIndex(int p_index)
5 {
6 m_index = p_index;
7 }
8
9 // Getter de la variable membre m_index
10 int CObject::GetIndex()
11 {
12 return m_index;
13 }
14
15 ...
16
INF3034 – Programmation orientée objet 31
POO – Encapsulation
 En C++
Utilisation :

1 #include "object.h" main.cpp


2
3 int main(int argc, char **argv)
4 {
5 CObject obj;
6
7 // Appel du setter pour modification.
8 obj.SetIndex(7);
9
10 // Appel du getter pour lecture.
11 printf("%d\n", obj.GetIndex(7));
12
13 // Je ne peux pas accéder directement au membre.
14 // Ne compile pas !!!
15 obj.m_index = 21;
16 }
INF3034 – Programmation orientée objet 32
C++ – Notions
La surcharge d’opérateur

INF3034 – Programmation orientée objet 33


C++ – Surcharge des opérateurs
 Le C++ offre la possibilité de redéfinir les opérateurs pour des types
spécifiques
 C’est la surcharge d’opérateur.
 La plupart des opérateurs peuvent être surchargés.
 Exemple :
 Les opérateurs de calcul + - * /
 Les opérateurs d’incrément ++ --
 L’opérateur d’indexation []
 …

INF3034 – Programmation orientée objet 34


C++ – Surcharge des opérateurs
 Exemple :
Prenons l’exemple d’un objet temps qui contiendrait 3 membres entiers
définissant les heures, les minutes ainsi que les secondes.
En prenant deux objets temps t1 et t2, on peut vouloir les additionner entre
eux pour avoir la somme des deux temps.

INF3034 – Programmation orientée objet 35


C++ – Surcharge des opérateurs
 Sans surcharge d’opérateur

1 class CTemps { temps.h


2 public:
3 int m_h, m_m, m_s;
4 };
5
6 CTemps add(const CTemps& p_t1, const CTemps& p_t2);
7

1 CTemps add(const CTemps& p_t1, const CTemps& p_t2) { temps.cpp


2 CTemps res;
3 res.m_s = (p_t1.m_s+p_t2.m_s)%60;
4 res.m_m = (p_t1.m_m+p_t2.m_m)%60 + (p_t1.m_s+p_t2.m_s)/60;
5 res.m_h = p_t1.m_h+p_t2.m_h + (p_t1.m_m+p_t2.m_m)/60;
6 return res;
7 }

1 CTemps t = add(t1, t2); main.cpp

INF3034 – Programmation orientée objet 36


C++ – Surcharge des opérateurs
 Avec surcharge d’opérateur

1 class CTemps { temps.h


2 public:
3 int m_h, m_m, m_s;
4 };
5
6 CTemps operator+(const CTemps& p_t1, const CTemps& p_t2);
7

1 CTemps operator+(const CTemps& p_t1, const CTemps& p_t2) { temps.cpp


2 CTemps res;
3 res.m_s = (p_t1.m_s+p_t2.m_s)%60;
4 res.m_m = (p_t1.m_m+p_t2.m_m)%60 + (p_t1.m_s+p_t2.m_s)/60;
5 res.m_h = p_t1.m_h+p_t2.m_h + (p_t1.m_m+p_t2.m_m)/60;
6 return res;
7 }

1 CTemps t = t1 + t2; main.cpp

INF3034 – Programmation orientée objet 37


C++ – Surcharge des opérateurs
Nous pourrions maintenant imaginer une version en utilisant une méthode (au sein
de la classe) et non une fonction.
Sans surcharge d’opérateur, notre classe deviendrais donc :
temps.h
1 class CTemps
2 {
3 public:
4 int m_h;
5 int m_m;
6 int m_s;
7
8 CTemps add(const CTemps& p_temps);
9 };

Cela aurait un impact sur l’appel de la fonction :


1 CTemps t = t1.add(t2); main.cpp

INF3034 – Programmation orientée objet 38


C++ – Surcharge des opérateurs
 En gardant cette méthode avec la surcharge d’opérateur, on obtient :
temps.h
1 class CTemps
2 {
3 public:
4 int m_h;
5 int m_m;
6 int m_s;
7
8 CTemps operator+(const CTemps& p_temps);
9 };

 Dans ce cas là, la méthode n’a qu’un seul argument, et fait l’opération entre
l’objet courant et le paramètre.

INF3034 – Programmation orientée objet 39


C++ – Surcharge des opérateurs
 Avec surcharge d’opérateur, au sein de la classe

class
1 CTemps { temps.h
2 public:
3 int m_h, m_m, m_s;
4 CTemps operator+(const CTemps& p_temps);
5
6 };
7

1 CTemps CTemps::operator+(const CTemps& p_temps) { temps.cpp


2 CTemps res;
3 res.m_s = (m_s+p_temps.m_s)%60;
4 res.m_m = (m_m+p_temps.m_m)%60 + (m_s+p_temps.m_s)/60;
5 res.m_h = m_h+p_temps.m_h + (m_m+p_temps.m_m)/60;
6 return res;
7 }

1 CTemps t = t1 + t2; main.cpp

INF3034 – Programmation orientée objet 40


POO – Les concepts
L’héritage

INF3034 – Programmation orientée objet 41


POO – Héritage
 Une notion fondamentale de la POO est l’héritage.
 Imaginons un programme en lien avec les transports utilisant quatre types
d’objets : Voiture, Moteur, Route et Véhicule.
Quel genre de relation peut-on créer entre la classe Voiture et les trois
autres?

 Une voiture possède un moteur.  Le moteur fait partie de la voiture, c’est donc
un élément de cette classe.

INF3034 – Programmation orientée objet 42


POO – Héritage
 Une notion importante de la POO est l’héritage.
 Imaginons un programme en lien avec les transports utilisant quatre types
d’objets : Voiture, Moteur, Route et Véhicule.
Quel genre de relation peut-on créer entre la classe Voiture et les trois
autres?

 Une voiture utilise une route.  La route ne fait pas partie de la voiture, de même
que la voiture ne fait pas partie de la route.
Pas d’inclusion.

INF3034 – Programmation orientée objet 43


POO – Héritage
 Une notion importante de la POO est l’héritage.
 Imaginons un programme en lien avec les transports utilisant quatre types
d’objets : Voiture, Moteur, Route et Véhicule.
Quel genre de relation peut-on créer entre la classe Voiture et les trois
autres?

 Une voiture est un véhicule.  La voiture possède toute les caractéristique d’un
véhicule, plus certaines qui lui sont propres.

INF3034 – Programmation orientée objet 44


POO – Héritage
 Dans le dernier cas, il y a donc une relation d’héritage.
 Une voiture hérite des caractéristiques communes à tout véhicule et
possèdent les siennes.
 La classe Voiture est dérivée de la classe Véhicule.

INF3034 – Programmation orientée objet 45


POO – Héritage
 En C++
Déclaration :

1 class CBase base.h 1 class CDerivee : public CBase derivee.h


2 { 2 {
3 public: 3 public:
4 // Membres de la classe 4 // Membres de la classe
5 int m_membreBase; 5 int m_membreDerivee;
6 6
7 // Méthodes de la classe 7 // Méthodes de la classe
8 CBase(); 8 CDerivee();
9 ~CBase(); 9 ~CDerivee();
10 10
11 void setMembreBase(int p_base); 11 void setMembreDerivee(int p_derivee);
12 }; 12 };
13 13
14 14

INF3034 – Programmation orientée objet 46


POO – Héritage
classe : CBase
membres : méthodes :
m_membreBase setMembreBase()

Hérite de

classe : CDerivee
membres : méthodes :
m_membreBase setMembreBase()
m_membreDerivee setMembreDerivee()

INF3034 – Programmation orientée objet 47


POO – Héritage
classe : CVehicule
membres : méthodes :
int m_nbRoues void getNbRoues()

classe : CVoiture
membres : méthodes :
CMoteur m_moteur void roule(int p_vitesse)
int m_vitesseMax void klaxon(int p_duree)

INF3034 – Programmation orientée objet 48


POO – Héritage
classe : CVehicule
membres : méthodes :
int m_nbRoues void getNbRoues()

Hérite de

classe : CVoiture
membres : méthodes :
int m_nbRoues void getNbRoues()
CMoteur m_moteur void roule(int p_vitesse)
int m_vitesseMax void klaxon(int p_duree)

INF3034 – Programmation orientée objet 49


POO – Héritage
 Encapsulation
 Le mot clé private bloque l’accès aux données.
 Utilisation du qualificatif protected.
 Permet l’accès des données aux classes filles seulement.

 En règle général :
 Membre de la classe  protected
 Méthodes de la classe  public / protected

INF3034 – Programmation orientée objet 50


POO – Héritage
 Héritage public / privée
 Il est de déclarer un héritage public :
class CDerivee : public CBase
ou privée :
class CDerivee : private CBase

 Dans le premier cas, les membres hérités conservent les mêmes droits d’accès que
dans la classe de base.
 Dans le second (cas par défaut), tous les membres hérités deviennent privées dans
la classe dérivée.

INF3034 – Programmation orientée objet 51


POO – Héritage
 Constructeur
 Lors de l’appel du constructeur de la classe fille, le constructeur par défaut de la
classe mère est appelé.
 Possibilité de modifier le constructeur appelé :

1 CFille():
2 CMere(12, 7.3f)
3 {
4 ...
5 }

INF3034 – Programmation orientée objet 52


POO – Masquage
 Imaginons que la classe Vehicule possède une méthode print() affichant
« Je suis un véhicule ».
La classe Voiture hérite de Vehicule.
1 class CVehicule vehicule.h
2 {
3 public:
4 ...
5 void print();
main.cpp
6 };
1 int main(int argc, char **argv)
voiture.h
2 {
1 class CVoiture : public CVehicule
3 CVoiture maVoiture;
2 {
4 maVoiture.print();
3 public:
5 }
4 ...
5
6 };

INF3034 – Programmation orientée objet 53


POO – Masquage
 Possibilité de redéfinir une méthode de la classe mère
 Le masquage

1 class CVehicule vehicule.h


2 {
3 public:
4 ...
5 void print();
main.cpp
6 };
1 int main(int argc, char **argv)
voiture.h
2 {
1 class CVoiture : public CVehicule
3 CVoiture maVoiture;
2 {
4 maVoiture.print();
3 public:
5 }
4 ...
5
6 };

INF3034 – Programmation orientée objet 54


POO – Masquage
 Possibilité de redéfinir une méthode de la classe mère
 Le masquage

1 class CVehicule vehicule.h


2 {
3 public:
4 ...
5 void print();
main.cpp
6 };
1 int main(int argc, char **argv)
voiture.h
2 {
1 class CVoiture : public CVehicule
3 CVoiture maVoiture;
2 {
4 maVoiture.print();
3 public:
5 }
4 ...
5 void print();
6 };

INF3034 – Programmation orientée objet 55


POO – Masquage
 Si l’on souhaite appeler la méthode de la classe mère :

1 class CVehicule vehicule.h


2 {
3 public:
4 ...
5 void print();
main.cpp
6 };
1 int main(int argc, char **argv)
voiture.h
2 {
1 class CVoiture : public CVehicule
3 CVoiture maVoiture;
2 {
4 maVoiture.print();
3 public:
5 }
4 ...
5 void print();
6 };

INF3034 – Programmation orientée objet 56


POO – Masquage
 Si l’on souhaite appeler la méthode de la classe mère :

1 class CVehicule vehicule.h


2 {
3 public:
4 ...
5 void print();
main.cpp
6 };
1 int main(int argc, char **argv)
voiture.h
2 {
1 class CVoiture : public CVehicule
3 CVoiture maVoiture;
2 {
4 maVoiture.CVehicule::print();
3 public:
5 }
4 ...
5 void print();
6 };

INF3034 – Programmation orientée objet 57

Vous aimerez peut-être aussi