Vous êtes sur la page 1sur 45

CH2: Les principes de la

programmation orienté objet

HAJRI Sarra
Qu’est ce qu’un programme orienté objet?

 Ensemble d’objets autonomes et responsables qui


s’entraident pour résoudre un problème final en
s’envoyant des messages
Qu’est ce qu’un objet?

 Objet= Données+ méthodes (fonctions membres)


Qu’est ce qu’un objet?

• Un objet est une entité informatique comprenant :


– des données membres (ou champs ou attributs ou
variables d’instances)
– des fonctions membres (ou méthodes ou routines)
On appelle encapsulation le regroupement des variables
et des fonctions au sein d'une même entité.

Données membres

Fonctions membres

Ex : un objet vecteur est composé de trois réels et d’opérations telles que la


translation, le produit scalaire …

.
Qu’est ce qu’un objet?

• Un objet possède un état :


L’état correspond à la valeur de ses attributs à un instant
donné. Il peut varier au cours du temps.

• Un objet est décrit par une classe :


Une classe est un prototype qui définit des attributs et des
méthodes communes à tous les objets d'une certaine nature.
C’est donc un modèle utilisé pour créer plusieurs objets
présentant des caractéristiques communes.
Qu’est ce qu’un objet?

• Un objet possède une identité :


-Les objets peuvent être distingués grâce à leurs
existences inhérentes et non grâce à la description des
propriétés qu'ils peuvent avoir.
-Deux objets peuvent être distincts même si tous leurs
attributs ont des valeurs identiques
Définition d’une classe en C++
Classe en C++
 L'accès aux données et méthodes peut être réglementé :

Partie privée
Vision interne
Partie publique Vision externe

 L’accès aux données des objets est règlementé:


 Données privées : accès uniquement par des fonctions membres
 Données publiques: accès direct par l’instance de l’objet

• Un objet n’est vu que par ses spécifications


• Une modification interne est sans effet pour le fonctionnement
général du programme
• Meilleure réutilisation de l’objet
Classe : interface

C’est la description de la structure interne de la classe

class Ellipse
{ • Visibilité des membres :
– public : membres accessibles à
Vision private: tous
interne float m_cX, m_cY; – private : membres accessibles à
float m_a, m_b; partir de la classe ; accès
impossible par l’extérieur
public : – protected : membres accessibles
Vision void deplace(float dx, float dy); à partir de la classe et des
externe void zoom(float z); classes dérivées ; accès
float surface(); impossible par l’extérieur

};

NB : dans cet exemple, on a choisi de représenter l'ellipse en interne à la classe par les coordonnées de
son centre (cX, cY), par son grand axe a et par son petit axe b.
Classe : implantation

C’est la définition des fonctions associées

Interface de la classe Ellipse


void Ellipse::deplace(float dx, float dy)
class Ellipse {
{ m_cX += dx;
protected : Opérateur m_cY += dy;
float m_cX, m_cY; de portée }
float m_a, m_b;
public : void Ellipse ::zoom(float z)
void deplace(float dx, float dy); {
void zoom(float z); m_a *= z;
float surface();
m_b *= z;
};
}

float Ellipse ::surface()


{
return 3.14 * m_a * m_b / 4.;
}
Instance d’une classe

 C’est un objet initialisé à partir de la description figée d’une


classe
 Fonction membres publiques
• Les constructeurs
• Les destructeurs

Ne pas confondre instance d'objet et classe d'objets


Une instance de classe fait référence à une chose précise
Une classe désigne un groupe de choses similaires
Ex : Le vélo de mon voisin et le mien sont deux instances de
la classe vélo, même s’ils sont strictement identiques
Constructeur de classe
• Le constructeur est une fonction membre qui sert à initialiser les données membres
de l’objet
• Systématiquement appelé quand un objet est instancié.
• N’a pas de type de retour
• Porte le nom de l’objet

• Une même classe peut avoir plusieurs constructeurs

• Constructeurs particuliers :
• constructeur par défaut
• Ne contient aucun argument
• Automatiquement généré si aucun constructeur n’est défini
• A définir explicitement dans le cas contraire
• constructeur de copie
• Contient comme argument un objet du même type
• Sert à créer des clones d’objets
Constructeurs de classe : exemple

class Ellipse #include “ellipse.h” #include "ellipse.h"


{
public : Ellipse::Ellipse() int main()
Ellipse(); // Constructeur par défaut { {
Ellipse(float x, float y, float a, float b); m_cX = m_ cY = 0; Ellipse e1;
Ellipse(const Ellipse & e); m_a = m_b = 1; Ellipse e2;
} Ellipse e3(e1); // e3 est un clone de
protected : e1
float m_cX, m_cY; Ellipse::Ellipse(float x, float y, float a, float b) : Ellipse e4 = e1; // e4 est un clone de
float m_a, m_b; m_ cX(x), m_ cY(y), m_a(a), m_b(b) e1
{ return 0;
public : } }
void deplace(float dx, float dy);
void zoom(float z) ; Ellipse::Ellipse(const Ellipse & e)
float surface() ; {
}; m_ cX = e. m_ cX;
m_ cY = e. m_ cY;
m_a = e.m_a ;
m_b = e.m_b;
}

void Ellipse::deplace(float dx, float dy)


{
m_ cX += dx; m_cY += dy;
}

etc …
Destructeur de classe
• Fonction membre systématiquement appelée juste avant
la destruction d’un objet
• Porte le nom de la classe et est précédé de ~
• Pas de type de retour
• Pas d’arguments
• Un seul par classe
• Permet de libérer les ressources
Destructeurs de classe : exemple

ellipse.h ellipse.cpp prog.cpp


#include “ellipse.h” #include "ellipse.h"
class Ellipse
{ Ellipse::Ellipse() int main()
public : { {
Ellipse(); // Constructeur par défaut m_cX = m_ cY = 0; Ellipse e;
Ellipse (float x, float y, float a, float b); m_a = m_b = 1; Ellipse* pE = new Ellipse(2.5, 6.5, 12, 15);
Ellipse(const Ellipse & e); }
~Ellipse(); // Destructeur delete pE; // appelle le destructeur pour pE
etc …
protected : return 0;
float m_cX, m_cY; Ellipse::~ Ellipse()
float m_a, m_b; {

public : }
void deplace(float dx, float dy);
void zoom(float z); void Ellipse::deplace(float dx, float dy)
float surface(); {
}; m_cX += dx; m_cY += dy;
}

etc …
L’héritage
• L'héritage est un principe propre à la POO qui permet de
créer une nouvelle classe à partir d'une classe existante.

• La classe nouvellement créée, dite classe dérivée,


contient les attributs et les méthodes de la classe dont
elle dérive, auxquelles s’ajoutent de nouveaux attributs
et de nouvelles méthodes propres à la classe dérivée.

• L’héritage permet donc de définir une hiérarchie de


classes :
• La classe de base est une classe générique.
• Les classes dérivées sont de plus en plus spécialisées
L’héritage

 L’héritage permet de définir les bases d’un nouvel objet


à partir d’un objet existant
 Le nouvel objet hérite des propriétés de l’ancètre et peut
recevoir de nouvelles fonctionnalités
Héritage
L’héritage permet de spécialiser une classe en définissant une relation de type

Forme

Ellipse Rectangle

Cercle Carre

Un cercle est un spécialisation d'une ellipse, il en possède les propriétés plus d'autres
qui lui sont spécifiques. On dérive donc la classe Cercle de la classe Ellipse .
Héritage

ellipse.h cercle.h prog.cpp


class Ellipse #include “ellipse.h” #include "cercle.h"
{
public : class Cercle : public Ellipse int main()
Ellipse(); { {
Ellipse (float x, float y, float a, float b);
public : Cercle c(5, 5, 15);
Ellipse(const Ellipse & e); Cercle(); c. affiche();
~Ellipse();
Cercle (float x, float y, float diametre); return 0;
protected : ~ Cercle(); }
float m_cX, m_cY; public :
float m_a, m_b; };

public :
void deplace(float dx, float dy);
void zoom(float z); cercle.cpp
float surface(); #include <iostream.h>
}; Le constructeur de la classe dérivée
#include “cercle.h”
appelle généralement un des
Cercle::Cercle() : public Ellipse() constructeurs de la classe de base.
ellipse.cpp {
}
#include <iostream.h> Cercle::Cercle(float x, float y, float diametre) : public Ellipse( x, y, diametre,
diametre)
void Ellipse::affiche() {
{ }
std::cout << "Ellipse de grand axe " << m_a;
void Cercle::affiche()
std ::cout << " et de petitt axe " << m_b << "\n";
} {
std::cout << "Cercle de rayon " << m_a / 2 << "\n";
Fonctions et classes amies
Classe amis : Une classe amis peut accéder aux membres privés et protégés d’une
autre classe dans laquelle elle est déclarée comme ami. Il est parfois utile de
permettre à une classe particulière d’accéder à des membres privés d’une autre
classe

L’avantage de cette méthode est de permettre le contrôle des accès au niveau de la


classe concernée: on ne peut pas s’imposer comme fonction amie d’une classe si
cela n’a pas été prévu dans la classe

Par exemple, la classe Carre peut être autorisée à accéder aux membres privés de
Rectangle

class Rectangle {
private:
int x, y;
//Maintenant la classe Carre peut accéder aux membres
privés de Rectangle
friend class Carre;
};
Fonctions et classes amies

Quelques points importants sur les fonctions et classes amies :

 Les amis ne devraient être utilisés qu’à des fins limitées. s’il y’a trop de
fonctions ou de classes externes déclarées en tant qu’amis d’une classe,
cela diminue la valeur de l’encapsulation dans la programmation orientée
objet.

 L’amitié n’est pas réciproque. Si la classe A est un ami de B, alors B ne


deviendra pas automatiquement un ami de A.

 Les classes amies ne sont pas héritée


Fonctions et classes amies

Situations d’amitié

 Fonction indépendante, amie d’une classe ;


 Fonction membre d’une classe, amie d’une autre classe ;
  Fonction amie de plusieurs classes ;
 Toutes les fonctions membres d’une classe, amies d’une
autre classe.
Fonctions et classes amies
Fonction indépendante amie d’une classe

Utilisation d’une fonction amie coïncide qui examine la coïncidence de


deux objets de type point.
Introduire dans la classe point la déclaration d’amitié :friend int coïncide
(point, point) ;
pointVisibilité: privésConstructeur
Fonctions et classes amies
Fonction indépendante amie d’une classe

n amie
Fonctions et classes amies

Remarques:

char, A);
• L’emplacement de la déclaration d’amitié au sein de la classe point est
absolument indifférent.

• Généralement, une fonction amie d’une classe possédera un ou plusieurs


arguments ou une valeur de retour du type de cette classe
Fonctions et classes amies

Fonction membre d’une classe, amie d’une autre classe


Fonctions et classes amies

Fonction amie de plusieurs classes


Fonctions et classes amies
Touts les fonctions d’une classe amies d’une autre classe
Exercice

Ecrire un programme permettant de créer des objets ayant


chacun :
- un tableau de 5 éléments de type entier en tant que donnée ;
- une fonction pour remplir le tableau et une fonction pour
afficher le contenu du tableau en tant que méthodes.
Solution
Surdéfinition des opérateurs
 C++ autorise la surdéfinition des fonctions membres ou indépendantes en
fonction du nombre et du type d’arguments.

 C++ autorise également la surdéfinition des opérateurs portant au moins


sur un objet,tel que l’addition (+), la soustraction (-) ou l’affectation (=)
entre objets.

 Pour surdéfinir un opérateur ‘op’, il faut définir une fonction de nom :


‘operator op’.
Exemple
Point operator + (point,point);
Surdéfinition des opérateurs
1.1. Surdéfinition d’opérateur avec une fonction amie
class point
{
int x,y;
public:
point(int a=0,int b=0) {x=a; y=b;}
void affiche()
{cout<<″Point : ″<<x<<″ - ″ <<y<<endl;}
friend point operator + (point,point);
};
//-----------------------------------------
point operator + (point p1,point p2)
{
point p;
p.x=p1.x+p2.x;
p.y=p1.y+p2.y;
return p;
}
//--------------------------
main()
{
point o1(10,20); o1.affiche();
point o2(45,50); o2.affiche();
point o3; o3.affiche();
o3=o1+o2; o3.affiche();
o3=operator+(o1,o2); o3.affiche();
o3=o1+o2+o3; o3.affiche();
o3=operator+(operator+(o1,o2),o3); o3.affiche();
Surdéfinition des opérateurs
1.2. Surdéfinition d’opérateur avec une fonction membre

 L’expression ‘o1+o2’ sera interprétée par le compilateur comme l’expression


‘o1.operator+(o2);’.

 Le prototype de la fonction membre ‘operator+’ sera donc :


‘point operator+(point)’ .
class point
{
int x,y;
public :
point(int a=0,int b=0) {x=a; y=b;}
void affiche()
{ cout<<″Point : ″<<x<<″ - ″<<y<<endl; }
point operator + (point);
};
//----------------------------------------------
point point::operator+(point p1)
{
point p;
p.x=x+p1.x; p.y=y+p1.y;
return p;
}
//---------------------------
main()
{
point o1(10,20); o1.affiche();
point o2(40,50); o2.affiche();
point o3; o3.affiche();
o3=o1+o2; o3.affiche();
o3=o3+o1+o2; o3.affiche();
}
Surdéfinition des opérateurs
Les possibilités et les limites de la surdéfinition des opérateurs en C++

 Le symbole suivant le mot clé ‘operator’ doit obligatoirement être un


opérateur déjà défini pour les types de base

 Il faut conserver la pluralité (unaire, binaire) de l’opérateur initial.

 Lorsque plusieurs opérateurs sont combinés au sein d’une même expression,


ils conservent leurs priorités relatives et leurs associativités.
◊ : opérateur devant être surdéfini en tant que fonction membre.
polymorphisme
Le polymorphisme forme avec l’encapsulation et l’héritage les trois piliers des
langages orientés objets.

Une fonction polymorphe (ou virtuelle) est une méthode qui est appelée en
fonction du type d’objet et non en fonction du type de pointeur utilisé.

- Lorsqu’on appelle une fonction virtuelle pour un objet, le C++ cherche cette
méthode dans la classe correspondante. Si cette fonction n’existe pas dans la
classe concernée, le C++ remonte la hiérarchie des classes jusqu'à ce qu’il
trouve la fonction appelée.

- Une fonction virtuelle ne peut être appelée par une autre méthode de la classe.
- Une fonction virtuelle ne peut être utilisée dans le corps d’un constructeur ou
d’un destructeur.
- Définir une fonction virtuelle pure entraîne :

- Une méthode virtuelle pure est une méthode qui est déclarée mais non
définie dans une classe. Elle est définie dans une des classes dérivées de cette
classe.

 Une classe qui contient la définition d’une fonction virtuelle pure devient
une classe abstraite.

 La redéfinition des fonctions virtuelles pures est obligatoire dans toutes les
classes dérivées. Dans le cas contraire, les classes dérivées deviennent
obligatoirement abstraites (Une classe abstraite est une classe qui ne peut
être instanciée.
Polymorphisme
Un objet héritant une méthode d'une classe parente peut réagir de façon différente à l'appel de cette
méthode.
ellipse.h cercle.h
class Ellipse #include “ellipse.h” main.cpp
{
#include " cercle.h"
public : class Cercle : public Ellipse
Ellipse(); {
int main() La fonction deplace() n’est pas
Ellipse (float x, float y, float a, float b); public :
{ redéfinie dans la classe Cercle,
Ellipse(const Ellipse & e); Cercle();
Ellipse e(0, 0, 8.5, 10.2); appelle celle de Ellipse.
~Ellipse(); Cercle (float x, float y, float d);
~ Cercle(); e.deplace(-1, 1); La fonction affiche() est redéfinie
protected : public : e.affiche(); dans la classe Cercle, appelle celle
float m_cX, m_cY; virtual void affiche(); de Cercle.
float m_a, m_b; }; Cercle c(-2.5, 2.5, 7,4);
c.deplace(0.5, 1.5);
public : c. affiche();
void deplace(float dx, float dy); cercle.cpp Appelle la fonction affiche()
void zoom(float z); de la classe Ellipse.
#include “cercle.h” Ellipse *p1;
float surface();
virtual void affiche(); p1 = new Ellipse;
}; Cercle::Cercle() : public Ellipse() p1 ->affiche();
{
} Ellipse *p2; Si la fonction affiche() est
p2 = new Cercle; virtuelle et est redéfinie dans
Cercle::Cercle(float x, float y, float d) : p2->affiche(); la classe Cercle, appelle celle
ellipse.cpp public Ellipse( x, y, d, d)
de Cercle bien que le pointeur
{
#include <iostream.h>
return 0; soit de type Ellipse. C'est le
}
} mécanisme de polymorphisme
void Ellipse::affiche() d'héritage.
void Cercle::affiche()
{ {
std::cout << "Ellipse de grand axe " << m_a; std::cout << "Cercle de rayon ";
std ::cout << " et de petit axe " << m_b << "\n"; std::cout << m_a / 2 << "\n";
} }
Gestion des exceptions
De nombreux problèmes apparaissent pendant l’exécution d’un programme,
l’insuffisance de mémoire, la perte d’un fichier, la saisie non valide d’une
valeur Le rôle d’un programme consiste à prévoir ces erreurs, et à mettre en
œuvre des solutions de ces erreurs d’exécution.

C++ propose, à part l’utilisation de la valeur de retour des fonctions, une


nouvelle solution pour intercepter les erreurs : le mécanisme des exceptions.

1. Gestion des erreurs en utilisant les valeurs de retour des fonctions

int positive(int v)
{ if(v<0) return 0;
cout<<«Valeur positive \n»;
return 1 ;

Dans ce programme le contrôle d’erreurs est alourdie par les ‘if’


imbriqués.
Gestion des exceptions
2. Mise en oeuvre des exceptions
Pour mettre en oeuvre des exceptions sans se baser sur les valeurs de retour des
fonctions, on doit :
 Définir une classe d’exception.
 Lancer l’exception (throw).
 Intercepter l’exception.

2.1. Définir une classe d’exception


Une classe d’exception correspond à une classe C++ qui peut fournir des informations
sur une erreur.

Exemple
class erreur
{
………………
};

On peut ajouter à la classe ‘erreur’ autant de données et de fonctions membres.


Gestion des exceptions
2.2. Lancer l’exception
Toute fonction qui souhaite lancer une exception doit utiliser un nouvel
opérateur du langage C++ throw, suivi par un objet créé à partir d’une classe
d’exception, cet
opérateur permet de quitter la fonction qui l’utilise et d’informer la fonction
appelante qu’une exception à été générée.

Exemple
void positive(int v)
{
if(v<0)
{
erreur er;
throw er;
}
cout<<"Valeur positive \n";
Gestion des exceptions
2.3. Intercepter l’exception
Pour intercepter une exception, C++ fournit une syntaxe basée sur
l’utilisation des blocs try et d’un ou plusieurs blocs catch :
try
{
//Appels de fonctions pouvant générer des erreurs
}
catch (classe d’exception)
{
//Ce bloc s’exécute pour une exception de type
//‘classe d’exception’
}
catch(…)
{
//Ce bloc s’exécute pour toutes les exceptions
//en dehors de la classe d’exception
}
Gestion des exceptions
Si une exception est envoyée par une de ces fonctions appelées dans le bloc ‘try’, le
mécanisme d’exception entraînera les étapes suivantes :
- Tous les objets créés dans le bloc ‘try’ sont détruits’
- Le programme sort du bloc ‘try’ après la fonction qui a entraîné l’exception et
n’exécute pas les instructions situées après cette fonction.
- Le C++ exécute dans l’ordre soit le bloc ‘catch’ correspondant à l’exception
interceptée si elle existe, soit le bloc ‘catch(…)’ si aucune de ces conditions n’est
remplie, cela entraîne la fin de l’exécution du programme, si un des blocs ‘catch’ a
été utilisé, le programme continu à exécuter les instructions situées après ce bloc
s’il y en a.

Remarque
Dans un bloc ‘catch’ on peut par exemple :
- arrêter le programme avec ou sans message utilisateur.
- corriger le problème avec ou sans message utilisateur
- uniquement informer l’utilisateur.
class erreur { };
void positive(int v)
{ if(v<0) throw erreur();
cout<<"Valeur positive \n";
}
void inf(int v,int max)
{ if(v>max) throw erreur();
cout<<"Valeur inférieure à : "<<max<<endl;
}
void sup(int v,int min)
{ if(v<min) throw erreur();
cout<<"Valeur supérieure à : "<<min<<endl;
}
//--------------------------------------------------------
main()
{
int minimum=10; int maximum=100;
try
{
int n;
cout<<"Saisir une valeur entière : "; cin>>n;
positive(n);
inf(n,maximum);
sup(n,minimum);
cout<<"Valeur correcte !\n";
}
catch(erreur er)
{
cout<<"valeur incorrecte! \n";
}
catch(...)
{
cout<<"Erreur inconnue !\n";
}

Vous aimerez peut-être aussi