Vous êtes sur la page 1sur 110

Programmation Oriente Objet

Plan du document
De la programmation classique la POO Avantages de la POO Exemples dobjets Objet logiciel
tat Comportement Identit

Concept de classe
Catgorie Classe Instance Constructeur

Hritage Association

Objectif : crire une squence d'instructions de telle faon qu'un ordinateur produise une sortie approprie pour une certaine entre Ingrdients :
dcomposition fonctionnelle variables passages de paramtres tests boucles structures

Le programme est une fonction principale int main(argc, argv[]) Cette fonction appelle des sous-fonctions Qui en appellent d'autres

main()

init()

calcule()

trie()

affiche() permute()

factorise()

compare()

Tous les ingrdients de la programmation procdurale classique sont prsents Mais la dcomposition fonctionnelle n'est pas assez structurante pour des programmes trs complexes Structurer le programme autour des objets manipuls Les traitements sont associs aux objets Sparation plus claire entre donnes et traitements

main()

Donnes

init()

calcule() Donnes

factorise() trie() compare() permute()

Donnes

Donnes

trie() init() calcule() compare() factorise() permute()

Avantages de la programmation objet Habituellement, un programme c'est une suite d'instructions. L'ordinateur est trs bte et il faut tout lui dtailler. Exemple programme douverture de porte
Mettre la main sur la poigne de la porte Tourner la poigne Pousser la porte Mettre le doigt sur l'interrupteur Appuyer sur l'interrupteur pour allumer l'ampoule

Tout se passe trs bien. Mais qu'est-ce qui se passe par exemple si on met une porte automatique ? Le programme sera incapable de trouver la poigne et d'ouvrir la porte !

En programmation objet, on associe aux objets des actions (aussi appelles mthodes). Par exemple, l'objet porte on peut associer la mthode ouvrir. De mme pour l'ampoule on pourrait associer une mthode allumer, teindre, etc. Le programme devient plus simple:

porte.ouvrir ampoule.allumer
On a plus besoin de savoir comment la portes'ouvre. On se contente de l'ouvrir. Pour indiquer qu'on applique la mthode (ouvrir) sur l'objet (porte), on note souvent objet.mthode (ici : porte.ouvrir).

Bien sr il faut dtailler ce que fait la mthode ouvrir de porte et la mthode allumer de lumire. On ne va pas dtailler dans le programme ce que fait la mthode ouvrir, mais on va le dtailler dans l'objet lui-mme. C'est normal, puisque la mthode ouvrir ne s'applique qu' la porte, pas la lumire:

porte.ouvrir: Mettre la main sur la poigne Tourner la poigne Pousser la porte

On peut changer la porte en mettant une porte automatique. On peut aussi l'ouvrir (mme si la porte elle-mme ne s'ouvre pas de la mme faon):

porte.ouvrir: Se placer devant la porte Attendre que la porte soit compltement ouverte

Mais votre programme pourra l'ouvrir sans rien changer: porte.ouvrir ampoule.allumer Le programme principal : il est inchang malgr le changement de porte

La programmation objet a plusieurs intrts, entre autres: Vous pouvez utiliser des objets sans savoir comment ils sont programms derrire (c'est le cas notre ouverture de porte). Les objets peuvent tre modifis sans avoir modifier votre programme (c'est aussi le cas ici). Les objets sont facilement rutilisables dans de nouveaux programmes. Les langages objets offrent des mcanismes pour permettre ce genre de programmation.

Quest-ce quun objet ?

Objets de la vie courante


Rve titi mange 0605040302 0102030405 grosminet

123CDE91 garfield

parle odie 001-DF-YTR poursuit 007BEJ06 Dupond java 2 45BEJ91 0203040506 felix Dupont poursuit

Les objets cooprent

Objet bote noire


Services rendus par lobjet :
Dmarrer ; Arrter ; Acclrer ; Freiner ; Climatiser

Fonctionnement interne ???

Objet logiciel
Abstraction
Reprsentation abstraite des entits du monde rel ou virtuel dans le but de les piloter ou de les simuler

Programme, logiciel
Service

Message = demande de service

Objet = tat + Comportement + Identit

tat

unObjet

Tlphone portable

voirRpertoire()

appeler (Bob) appeler (personne)

chercher Numero (personne)

tat

monTlphone

recevoir msg (msg)

appeler (Bob et Paulette)

tat dun objet


Attribut
Information qui qualifie lobjet qui le contient Peut tre une constante

tat
Identit Valeurs instantanes de tous les attributs dun dobjet objet attribut volue au cours du temps compte001 : CompteBancaire Dpend variablede lhistoire de lobjet solde DEBITAUTORISE constant
attribut

Comportement dun objet


Dcrit les actions et les ractions dun objet
Comptences dun objet

Service = opration = mthode


Comportement dclench par un message
compte001: CompteBancaire consulter ()
consulter() est un service offert par compte001

dupont : Client

Les objets communiquent


Permet de reconstituer une fonction par une mise en collaboration dun groupe dobjets : envois de messages successifs
dupont : Client crditX : Banque c1 : CompteBancaire c2 : CompteBancaire

virer(m, c1, c2) retirer (m) dposer (m)

Identit dun objet


Caractrise son existence propre Indpendant du concept dtat Permet de dsigner tout objet de faon non ambigu

compte001 :CompteBancaire

compte112 :CompteBancaire

1000

1000

Classe
Description dune famille dobjets
Mmes attributs Mme mthodes
Spcification

Ralisation (implantation)
Dcrit comment la spcification est ralise

Gnrateur d'objets = moule

Classe CompteBancaire

CompteBancaire CompteBancaire solde dposer() retirer()

Nom de la classe attributs

oprations

Instance
Chaque objet appartient une classe Relation dinstanciation instance de

CompteBancaire
<<instanciation>> compte001 : CompteBancaire

Classe Relation dinstanciation

Instance solde : 1000

Constructeur
Un objet doit tre cr au sein dune classe == moule Mthode particulire : constructeur
Construit lobjet avec ses attributs, ses mthodes Initialise les valeurs des attributs Nom du constructeur = Nom de la classe CompteBancaireNom de la classe soldeattributs
Constructeur

CompteBancaire() oprations dposer() retirer()

Hritage: les concepts

Gnralisation et spcialisation
Gnralisation
Factoriser les lments communs (attributs, oprations...) dun ensemble de classes
Simplifier les diagrammes (regroupements smantiques) ClasseMre

est un , est une sorte de

Spcialisation

Gnralisation

Spcialisation
Utiliser les caractristiques d'une classe dj identifie et en spcifier de nouvelles.
ClasseFille

Hirarchie de classe
Arborescence des hritages

Gnralisation

CompteChque
montantDcouvAutoris

CompteEpargne
taux intrts

solde

solde
calculerIntrts () crditerIntrts () changerTaux ()

changerDecouvert ()

dposer () retirer ()

dposer () retirer ()

Constat: des caractristiques communes

Gnralisation
CompteBancaire solde dposer () retirer()

Nota : La smantique de retirer est diffrente

CompteCheque
montantDcouvertAutoris

CompteEpargne
taux intrts

changerDecouvert ()

retirer ()

calculerIntrts () crditerIntrts () changerTaux ()

Spcialisation
Un PlanEpargneLogement est un CompteEpargne ayant des caractristiques propres
PlanEpargneLogement dure dateDebut priodiciteVersement montantVersement CompteEpargne taux intrts calculerIntrts () crditerIntrts () changerTaux ()

calculerMontantPrt() retirer()

PlanEpargneLogement

Arborescence d'hritage
CompteBancaire solde dposer () retirer() PlanEpargneLogement dure dateDebut priodiciteVersement montantVersement

CompteChque
montantDcouvAutoris

CompteEpargne taux intrts calculerIntrts () crditerIntrts () changerTaux ()

changerDecouvert () retirer ()

calculerMontantPrt() retirer()

Redfinition dune mthode


CompteBancaire solde CompteChque : retrait autoris suivant dcouvert dposer () CompteEpargne : pas de dcouvert autoris

Smantique de la mthode retirer :

retirer ()
PlanEpargneLogement : pas de retrait

PlanEpargneLogement dure dateDebut priodiciteVersement montantVersement calculerMontantPrt()

CompteEpargne taux intrts calculerIntrts () crditerIntrts () changerTaux ()

CompteChque montantDcouvertAutoris ChangDecouvert ()

retirer ()

retirer ()

Redfinition dune mthode


class CompteBancaire { // void retirer ( double montant ) { if (solde >= montant) solde = solde - montant; } //... } class CompteChque public CompteBancaire { // Redfinition de retirer() void retirer ( double montant ) { if (solde +decouvert >= montant) solde = solde - montant; } //... } class CompteEpargne public CompteBancaire { // Pas de redfinition de retirer() // car hritage de CompteBancaire }

class PlanEpargneLogement public CompteBancaire { void retirer ( double montant ) { cout <<" Interdit !! "; } }

Hritage et sous classes


Hritage Mcanisme permettant de driver une classe partir d'une classe existante Permet de classer Etendre structurellement et comportementalement une classe Permet de construire Rutiliser le code d'une classe existante Classe drive Hrite de toutes les caractristiques de son (ses) anctre(s) Peut avoir des caractristiques propres Peut redfinir des caractristiques hrites

Associer les classes : Les concepts

Association

Agence

grer

Client

possder

Compte

Une agence gre plusieurs clients. Un client possde un et un seul compte courant.

Multiplicits les plus courantes


Agence
grer 1 * possder

Client
11

Compte

1 0..1 M..N * 0..* 1..*

Un et un seul Zro ou un De M N (entiers naturels) De zro plusieurs De zro plusieurs D'un plusieurs

Association simple: une rfrence comme attribut


Client identifiant : entier anneOuvertureCompte : entier compteCourant : CompteBancaire CompteBancaire

Lattribut compteCourant est une rfrence sur un objet de la classe CompteBancaire

Association multiple : Tableau de rfrences sur des objets


uneAgence:Agence nom adresse lesClients

* 500

BNP EVRY

indice 0

500

unClient:Client

Une traduction d'associations


Agence directeur : chane adresse : chane changerDirecteur(...) ajouterUnClient(...) Client Compte

grer

nom : chane ge : entier * vieillir() changerNom(...)

possder

lesDpts : entier[100] lesRetraits : entier[100]

1
dposer(...) retirer(...)

Agence directeur : chane adresse : chane lesClients : Clients[500] changerDirecteur(...) ajouterUnClient(...)

Client nom: chane ge: entier compte : Compte vieillir() changerNom(...)

Une agence gre une liste de clients. La rfrence de son compte fait partie des attributs dun client.

Programmation Objet en C++

Meilleur C
Le langage C++ se veut un langage C amlior. Il possde des fonctionnalits supplmentaires, et notamment * la surcharge de fonctions * le passage par rfrence * l'emplacement des dclarations * l'allocation dynamique Les apports spcifiques de C++ sont * l'aide l'abstraction de donnes: dfinition de types de donnes, et de leur implmentation concrte. * l'aide la programmation objet: hirarchie de classes et hritage.

Incompatibilits entre C et C++


Toute fonction doit tre dfinie avant utilisation ou tre dclare par un prototype float fct (int, double, char*); (En C, une fonction non dclare est suppose de type de retour int.) Une fonction qui ne retourne pas de valeur a le type de retour void. Le qualificatif const peut tre utilis pour une expression Constante ncessaire pour la taille d'un tableau const int N = 10; // remplace #define N 10 int valeurs[N];

Entres-sorties
Les entres et sorties sont gres dans C++ travers des objets particuliers appeles streams ou flots. Inclure <iostream.h> Deux oprateurs sont surchargs de manire approprie pour les flots: * l'oprateur d' insertion << (criture) * l'oprateur d' extraction >> (lecture) Trois flots prdfinis sont * cout attach la sortie standard; * cerr attach la sortie erreur standard; * cin attach l'entre standard;

E/S exemple 1
#include <iostream.h> main() { cout << "Bonjour, monde !\n"; } Plusieurs expressions: cout << ex_1 << ex_2 << ... << ex_n ; Plusieurs ''lvalues'': cin >> lv_1 >> lv_2 >> ... >> lv_n ; Les types crits ou lus sont char, short, int, long, float, double, char* Exemple #include <iostream.h> int i; main() { cout << "Un entier : "; cin >> i; cout << "Le carre de " << i <<" est " << i*i << endl; }

Commentaires
/* commentaire // commentaire commentaire */ // commentaire

Emplacement des dclarations


Une dclaration peut apparatre en n'importe quelle position d'un corps de classe ou de fonction, mais doit prcder son utilisation. int n; n = 3; int q = 2*n-1; for (int i = 0; i<n ; i++) {...} // dconseill

Arguments par rfrence


Enfin le passage par rfrence qui manque au C. Un paramtre dont le nom est suivi de & est transmis par rfrence, donc pas de copie de l'argument l'appel; possibilit de modifier l'argument. Dclaration void echange(float&, float&) ; Dfinition void echange(float& a, float& b) { float t = a; a = b; b = t; } Exemple float x = 2, y = 3; echange (x, y); cout << x <<","<< y; //Affiche 3,2

Rfrences Constantes
Passage par rfrence constante pour ne pas copier l'argument l'appel; ne pas modifier l'argument : void afficher(const objet&); Passage par rfrence constante permet d'assurer l'encapsulation en vitant la copie sur la pile de structures trop grande.

Arguments par dfaut


Les derniers arguments d'une fonction/mthode peuvent prendre des ''valeurs par dfaut''. Dclaration float f(char, int = 10, char* = "Tout"); Appels f(c, n, "rien") f(c, n) // <-> f(c, n, "Tout") f(c) // <-> f(c,10, "Tout") f() // erreur Seuls les derniers arguments peuvent avoir des valeurs par dfaut. float f(char = 'a', int, char* = "Tout"); // erreur

Surcharge
Un mme identificateur peut dsigner plusieurs fonctions, si elles diffrent par la liste des types de leurs arguments. float max(float a, float b) { return (a > b) ? a : b;} float max(float a, float b, float c) { return max(a, max(b, c));} float max(int n, float t[]) { if (!n) return 0; float m = t[0]; for (int i = 1 ; i < n; i++) m = max(m, t[i]); return m; } void main() { float x, y, z; float T[] ={11.1, 22.2, 33.3, 44.4, 7.7, 8.8 }; x = max (1.86, 3.14); y = max (1.86, 3.14, 37.2); z = max (6, T); cout << x <<" "<< y <<" "<< z; }

Allocation dynamique
Deux Oprateurs Intgrs au langage. Les oprateurs new et delete grent la mmoire dynamiquement. new chose[n] alloue la place pour lments de type chose et retourne l'adresse du premier lment; delete addresse libre la place alloue par new. int* a = new int; // malloc(sizeof(int)) double* d = new double[100]; // malloc(100*sizeof(double))

Fonctions/Mthodes en ligne
Une fonction en ligne (inline) est une fonction dont les Instructions sont incorpores par le compilateur dans le module objet chaque appel. Donc il n'y pas d'appel : gestion de contexte, gestion de pile; Dclaration par qualificatif inline. inline int sqr(int x) { return x*x; } [ les mthodes dfinie dans le corps de classe sont inlines] [ les fonctions trop grandes ou rcursives ne sont pas inlines]

Classes et objets
Une classe est une structure, dont les attributs sont des donnes ou des mthodes. Un objet, ou une instance, est un exemplaire de cette structure. class Complexe { public: float re, im;//donnes void show(); //mthode }; On dclare des objets de la classe par: Complexe a, b; On les manipule de manire usuelle: a.re = b.im; b.re = 7; a.show();

La dfinition d'une mthode se fait soit en ligne, soit sparment; dans le deuxime cas, elle utilise l' oprateur de porte not :: pour dsigner la classe. void Complexe::show() { cout << re << ' ' << im; } A l'appel a.show(), la mthode est celle de la classe de a, donc Complexe::show(), et les champs re et im sont ceux de l'objet appelant, c'est--dire a.re et a.im.

La surcharge d'oprateurs permet de dfinir une forme agrable pour des oprations sur des objets. Complexe operator+(Complexe s, Complexe t) { Complexe w; w.re = s.re + t.re; w.im = s.im + t.im; return w; } On peut alors crire : Complexe a, b, c; ... a = b + c;

Classes
1. Objectif 2. Dclaration 3. Dfinition 4. Encapsulation 5. Constructeurs 6. Une classe de complexes 7. Une classe de rationnels 8. Surcharge d'oprateurs 9. Liste d'initialisation 10. Membres statiques 11. Mthodes constantes 12. La classe string

Objectifs
Une classe est la description d'une famille d'objets ayant mme structure et mme comportement. Une classe regroupe un ensemble d'attributs ou membres, rpartis en *un ensemble de donnes *un ensemble de fonctions, appeles mthodes.

Avantages !!! * simplifie l'utilisation des objets, * rapproche les donnes et leur traitement: c'est l'objet qui sait le mieux comment grer une demande, * renforce la robustesse du programme et la structure * simplifie la maintenance et la construction * permet l'encapsulation : possibilit de ne montrer de l'objet que ce qui est ncessaire son utilisation. * (permet de) masquer l'implmentation

La dclaration d'une classe donne la nature des membres (type, signature), et les droits d'accs: public, protected, private (dfaut). La dfinition d'une classe fournit la dfinition des mthodes. L'encapsulation peut se pratiquer en donnant l'utilisateur * un fichier en-tte contenant la dclaration de la classe; * un module objet contenant la version compile du fichier contenant la dfinition de la classe.

Dclaration
La syntaxe est celle des structures. Une struct est une classe dont tous les attributs sont publics. class Point { int x, y; public: void setPoint (int, int); void deplace (int, int); void affiche (); }; * La classe Point a deux membres donnes privs x et y. * Elle a trois mthodes publiques setPoint, deplace et affiche.

Dfinition
L' oprateur de porte :: indique la classe laquelle appartient la mthode. 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; }

Les champs x, y invoqus dans les mthodes sont ceux de l'objet qui appelle la mthode. Cet objet est explicitement accessible par le pointeur this. On peut crire void Point::setPoint(int a, int b) { this -> x = a; this -> y = b ; }

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

Encapsulation
Principe de programmation : Il s'agit de ne montrer l'utilisateur que ce qui lui est destin. * seules des fonction d'accs et de modification sont rendues publiques; * toute donne est prive ou protge; * l'implmentation peut ntre disponible que par un module objet. Exemple: Le projet est compos de trois fichiers * Un fichier point.h de dclaration de la classe Point * Un fichier point.c d'implmentation des mthodes de la classe * Un fichier main.c d'utilisation. Le fichier d'implmentation est terme remplac par un module objet point.o

// Fichier point.h class Point { int x, y; public: Point (int, int); void deplace (int, int); void affiche (); };
// Fichier point.c #include <iostream.h> #include "point.h" Point::Point(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; }

// Fichier main.c #include "point.h" void main() { Point a(1,2), b(3,-5); a.affiche(); b.affiche(); a.deplace(1,1); a.affiche(); }

Constructeurs
Les constructeurs permettent de dfinir les initialisations possible des instances d'une classe. * En C++, un constructeur a le nom de la classe, et pas de type de retour. * Une classe peut avoir plusieurs constructeurs. * Un constructeur sans arguments est appel constructeur par dfaut. - ce constructeur existe implicitement, s'il est le seul constructeur. - la dfinition d'un deuxime constructeur exige que l'on dfinisse explicitement le constructeur par dfaut si l'on veut s'en servir.

Le constructeur par dfaut est utilis * lors de la dfinition d'un objet, par X x; * lors d'une allocation, par px = new X; Sauf criture explicite, le constructeur par dfaut n'effectue pas d'action.

Destructeur
Le destructeur est not ~X() pour une classe X. Il est utilis * lorsque le programme quitte le bloc o l'objet est dclar * pour la destruction explicite par delete px; Le destructeur permet de spcifier ce qui doit tre fait quand l'objet est dsallou. Ceci est important quand un constructeur fait de l'allocation explicite.

Exemple constructeur
Remplacement de la mthode setPoint par un constructeur : class Point { int x, y; public: Point (int, int); void deplace (int, int); void affiche (); }; Le constructeur Point(int,int) rend inoprant le constructeur par dfaut s'il n'est pas redfini. Le constructeur est employ en passant les arguments en paramtre. C'est une abrviation de Point a = Point(1.5,2.5), b = Point(3,-5); Point::Point(int a, int b) { x = a; y = b ; }... void main() { Point a(1.5,2.5), b(3,-5); ... }

Variations * Un constructeur simple peut tre dfini en ligne, par class Point { int x, y; public: Point (int a, int b) {x = a; y = b;} ... }; * Au lieu de construire l'objet puis d'affecter des valeurs aux champs, on peut initialiser les champs avec les valeurs, par Point (int a, int b) : x(a), y(b) {}

Tableaux d'Objets
Tableaux d'objets attention le constructeur par dfaut est appel sur chaque lment du tableau. main () { const int taille = 7; Point* a = new Point[taille]; // par defaut for (int i=0; i < taille ; i++) cout << i << a[i].x << a[i].y << endl; delete [] a; } La libration d'un tableau d'objets par delete [] * parcourt le tableau et appelle le destructeur sur chaque lment du tableau; * puis libre le tableau.

Construction&Destruction
La mention explicite du constructeur par dfaut et du destructeur signifie leur redfinition. class Id { string nom; public: Id() { cout << "Entrez votre nom : ";cin >> nom;} ~Id(){ cout <<"Mon nom est "<< nom <<endl; } }; Le programme se rduit : Ou: void main() Id pierre,paul; { void main(){} Id pierre, paul; } Voici une trace d'excution: Entrez votre nom : Pierre Entrez votre nom : Paul Mon nom est Paul Mon nom est Pierre

Une classe de Complexes


class Complexe { double re, im; public: Complexe() { re = im = 0;} Complexe(double , double ) ; Complexe(double x) ; }; Complexe::Complexe(double x, double y) {re = x; im = y;} Complexe::Complexe(double x) {re = x; im = 0;} Si les fonctions sont courtes, on les dfinit en ligne. Ensemble: class Complexe { double re, im; Complexe() { re = im = 0;} Complexe(double x, double y) {re = x; im = y;} Complexe(double x) {re = x; im = 0;} } Le constructeur par dfaut Complexe() est explicit pour fixer des valeurs de dpart. Ainsi Complexe s, t; dfinit deux complexes s, t initialiss zro.

En utilisant les arguments par dfaut, les trois constructeurs se rduisent en un seul. Ici, on remplace l'affectation par l'initialisation, et on ajoute une mthode: class Complexe { double re, im; Complexe(double r = 0, double i = 0) : re(r), im(i) {} double getModule() { return sqrt(re*re + im*im); } } On s'en sert * l'initialisation, par exemple Complexe h, a(3,5), b = Complexe(2,4); Complexe c(5), d = Complexe(6), e = 7; Par conversion de type, 7 est transform en Complexe(7) puis copi.

Une interface plus complte


La dclaration est: #include <iostream.h> #include <math.h> class Complexe { public : Complexe(double re = 0, double im = 0); double getRe(); double getIm(); double getModule(); void setRe(double); void setIm(double); void showXY() { cout << getRe() << " " << getIm() <<" "; } private: double re, im; // Premiere implementation }

// Implmentation Complexe::Complexe(double re, double im): re(re), im(im){} double Complexe::getRe() { return re; } double Complexe::getIm() { return im; } double Complexe::getModule() { return sqrt(re*re+im*im); } void Complexe::setRe(double x) { re = x; } void Complexe::setIm(double y) { im = y; } // Utilisation void main() { Complexe a = Complexe(3,4); cout << a.getModule() << endl; a.showXY(); a.setRe(20); a.setIm(20); cout << a.getModule() << endl; a.showXY(); Complexe b(5); cout << b.getModule() << endl; b.showXY();

Les rationnels
L'objectif est de montrer l'utilisation de surcharges, cette fois-ci sur les oprateurs arithmtiques et d'entre-sortie. -3547/977777 0/1 etc Un nombre rationnel est toujours rduit, et le dnominateur est toujours strictement positif. D'o la ncessit d'une mthode de rduction. [rduit: numrateur et dnominateur sont des entiers premiers entre eux, c-a-d les plus petits possibles.]

class Rat { static int pgcd(int,int); public: int num, den; void red(); // reduit la fraction Rat(int n = 0) : num(n), den(1) {} Rat(int n, int d) : num(n), den(d) { red();} }; La rduction fait appel une fonction de calcul de pgcd: void Rat::red() { int p = pgcd( (num > 0) ? num : -num, den); num /= p; den /= p; } int Rat::pgcd(int a, int b) { return (!b) ? a : pgcd(b, a%b); } Une mthode dclare static (Mthode de classe) * peut tre appele sans rfrence une instance * peut tre appele par rfrence sa classe * n'a pas de pointeur this associ. Une donne dclare static (Donne de classe) est commune toutes les instances, une seule allocation et donc une seule valeur.

Exemple de Surcharge d'oprateurs


Comme toute fonction, un oprateur peut galement tre surcharg. Pour surcharger un oprateur op on dfinit une nouvelle fonction de Nom operatorop Par exemple operator= ou operator+. La syntaxe est type operatorop(types des oprandes) { /* corp de l'oprateur */ return valeur; } Par exemple Rat operator+(Rat,Rat); L'expression a+b est implicitement traduite par le compilateur en operator+(a, b) Un oprateur surcharg peut se dfinir * au niveau global, * comme membre d'une classe. Apport de la surcharge: le calcul s'crit comme pour un type lmentaire !

Nous dfinissons les quatre oprations arithmtiques par: Rat operator+(Rat a, Rat b) { return Rat(a.num*b.den + a.den*b.num, a.den*b.den); } Rat operator-(Rat a, Rat b) { return Rat(a.num*b.den - a.den*b.num, a.den*b.den); } Rat operator/(Rat a, Rat b) { return Rat(a.num*b.den, a.den*b.num); } Rat operator*(Rat a, Rat b) { return Rat(a.num*b.num, a.den*b.den); } Le moins unaire se dfinit par: Rat operator-(Rat a) { return Rat(-a.num, a.den); }

Les rationnels pass en argument ne sont pas modifis, on peut donc les spcifier const Rat&. Rat operator+(const Rat& a, const Rat& b) {...} Rat operator-(const Rat& a, const Rat& b) {...} ... L'oprateur d'incrmentation += se surcharge galement: Rat& operator+=(Rat& a, const Rat& b) { a.num = a.num*b.den + a.den*b.num; a.den = a.den*b.den; a.red(); return a; } L'un des appels a += b; //ou operator+=(a,b); * construit dans a pass par rfrence, la valeur incrmente, * et en transmet la rfrence en sortie. Ici, une dfinition en mthode est plus logique

Donne membre statique


Une donne membre statique est spcifie par static. * Elle n'est instancie qu'une seule fois; * Elle est commune toutes les instances de la classe; * Si un objet la modifie, elle est modifie pour tous les objets. * Elle est initialise avant utilisation.

Exemple de donne statique


#include <iostream.h> class XY { public: static int app; XY() { cout << "+ : " << ++app << endl; } ~XY() { cout << "- : "<< app-- << endl; } }; int XY::app = 0; // initialisation globale void main() { XY a, b, c; { XY a, b; } XY d; } Rsultat: +:1 +:2 +:3 +:4 +:5 -:5 -:4 +:4 -:4 -:3 -:2 -:1

Copie et affectation

1. Constructeurs 2. Constructeur de copie 3. Affectation 4. Conversions La copie et l'affectation sont des opration trs importante.

Constructeurs

Les constructeurs se classent syntaxiquement en 4 catgories 1. le constructeur par dfaut, sans argument, 2. les constructeurs de conversion, un argument 3. le constructeur de copie, un argument 4. les autres constructeurs.

constructeur de conversion
Un constructeur de conversion sert souvent la promotion. Exemple: class Rat { int num, den; public: ... Rat(int n) { num = n; den = 1;} ... }; On s'en sert pour la conversion Rat r, s; ... r = s + 7; L'entier 7 est promu en Rat(7) avant l'addition.

Constructeur de copie
Chaque classe possde un constructeur de copie (ne pas confondre avec l'oprateur d'affectation). Le constructeur de copie par dfaut copie membre membre en utilisant le constructeur de copie de chaque membre, et une copie bit bit pour les types de base (copie superficielle). Ceci est insuffisant en prsence d'adresses. Il faut alors allouer de nouvelles zones mmoire (copie profonde).

Le constructeur de copie est utilis * lors d'une initialisation: X x = y; X x(y); X* x = new X(y); o y est un objet dj existant. * lors du retour d'une fonction retournant un objet par valeur; * lors du passage d'un objet par valeur une fonction. Le constructeur de copie a deux prototypes possibles : X (X&); X (const X&); L'argument est donc un objet de la classe X pass par rfrence (videmment !) et ventuellement spcifi comme Non modifiable dans le constructeur.

Voici une classe Pt possdant: * Un constructeur de copie Pt(const Pt& p) * Un oprateur d'affectation Pt& operator=(const Pt& p) #include <iostream.h> class Pt { int x, y; public: Pt(int abs = 1, int ord = 0): x(abs), y(ord) {} //implantation par dfaut: Pt(const Pt& p) : x(p.x), y(p.y){} //implantation par dfaut: Pt& operator=(const Pt& p) { x = p.x; y = p.y; return *this; } };

Affectation
L'affectation et la copie sont des oprations diffrentes. * le constructeur de copie sert l'initialisation et pour le passage de paramtres. Il construit l'objet. * l'oprateur d'affectation = pour l'affectation dans une expression. Il retourne un objet ou une rfrence. L'oprateur d'affectation est un oprateur, et peut donc tre redfini explicitement par une fonction operator=(). Chaque classe possde un oprateur d'affectation par dfaut. L'affectation est superficielle comme la copie, et consiste en une affectation membre membre.

La signature de l'oprateur est X& operator=(X&) X& operator=(const X&) X operator=(X&) X operator=(const X&) et l'expression y = x quivaut y.operator=(x) Le rsultat de l'affectation est donc dans l'objet appelant.

Fonctions amies
L'amiti permet d'accder aux parties prives. Une ''dclaration d'amiti'' incorpore, dans une classe X, les fonctions autorises accder aux membres privs. Une fonction amie a le mme statut qu'une fonction membre de X. Fonction globale class X { ... friend f(X); } Ici, f est autorise accder aux membres privs de la classe X.

Fonction membre de Y class Y { ... void f(X& x); } class X { ... friend Y::f(X& x); } void Y::f(X& x) { x.priv = 1; // ok x.prot = 1; // ok x.publ = 1; // ok } Une classe entire est une classe amie par class X { ... friend class Y; }

Oprateurs amis
Une fonction amie d'une classe a les mmes droits qu'une fonction membre, et en particulier peut accder aux membres privs de la classe. class Rat { int num, den; // prives public: int getNum() {return num;} int getDen() {return den;} Rat(int n = 0, int d = 1) : num(n), den(d) {} };

L'addition Rat operator+(const Rat& a, const Rat& b) { int n = a.getNum()*b.getDen() + a.getDen()*b.getNum(); return Rat(n, a.getDen()*b.getDen()); } s'crit plus efficacement et plus lisiblement: Rat operator+(const Rat& a, const Rat& b) { return Rat(a.num*b.den + a.den* b.num, a.den*b.den); } Or num et den sont privs. Pour les rendre accessibles, l'oprateur est dclar ami, dans la dclaration de la classe Rat, par friend Rat operator+(Rat, Rat); Une fonction amie a les mmes droits qu'une fonction membre.

Syntaxe
Un oprateur est unaire, binaire. Un oprateur peut tre dfini * soit comme fonction globale un ou deux arguments * soit comme fonction membre avec un argument de moins. La syntaxe est * oprateur binaire au niveau global: type operatorop(type,type); Rat operator+(Rat,Rat); L'expression u+v quivaut operator+(u,v). * oprateur binaire membre de classe: type operatorop(type); Rat& operator+=(Rat); L'expression u += v quivaut u.operator+=(v).

* oprateur unaire au niveau global: type operatorop(type); Rat operator-(Rat); L'expression -u quivaut operator-(u). * oprateur unaire membre de classe: type operatorop(); Rat operator-(); L'expression -u quivaut u.operator-().

Un Conseil
* Choisir un oprateur global et ami lorsque l'opration est symtrique: + - * / == * Choisir un oprateur membre lorsque l'opration est asymtrique ou ncessite une rfrence : += class Rat { int num, den; public: ... Rat operator-(Rat); //membre : mauvais choix Rat& operator+=(const Rat&); //membre :bon choix friend Rat operator/(Rat , Rat ); //amie : bon choix };

Avec Rat Rat::operator-(Rat b) {return Rat(num*b.den - den* b.num, den*b.den);} Rat& Rat::operator+=(const Rat& d) { num = num*d.den + d.num*den; den = den*d.den; return *this; } Rat operator/(Rat a, Rat b) { return Rat(a.num*b.den, a.den*b.num); } Exemple cout << a << b << a-b << a.operator-(b) << a-1 << a+=2 << a; Rsultat 1/2 2/3 -1/6 -1/6 -1/2 3/2 3/2

Hritage
1. Objectif 2. Classe compose ou classe drive 3. Syntaxe 4. Accs aux donnes et mthodes 5. Classes drives et constructeurs 6. Hritage multiple

Objectif
L'hritage est l'un des principes fondamentaux de la programmation objet. Il a pour objectif de hirarchiser les classes et les objets. L'hritage est mis en oeuvre par la construction de classes drives. Une classe drive * contient les donnes membres de sa classe de base; * peut en ajouter de nouvelles; * possde a priori les mthodes de sa classe de base; * peut redfinir (masquer) certaines mthodes; * peut ajouter de nouvelles mthodes. L'hritage peut tre simple ou multiple.

Avantages:
* Une classe drive modlise un cas particulier de la classe de base, et peut donc utiliser la classe de base; * l'hritage encourage la recherche de la gnralit et de la gnricit; * une hirarchie de classes facilite la solution de problmes complexes; * facilite la maintenance, le dveloppement et les extensions; * peut ajouter de nouvelles mthodes.

Composition ou Hritage
Une classe est compose si certains de ses membres sont eux-mmes des objets. class Carte { class DescrHabitant { DescrHabitant h; protected: int age; string nom; float age; string domicile; }; }; 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 DescrResident : public DescrHabitant{ protected: string residence; }; La description d'un rsident est plus complte que celle d'un habitant: l'information supplmentaire est l'adresse de sa rsidence (qui peut tre diffrente de celle de son domicile).

Syntaxe
La syntaxe pour la dfinition d'une classe drive est class classe_derivee : protection classe_de_base {...}; Les types de protection sont public, protected, private. En gnral, on choisit public.

Des Exemples
* Une voiture comporte quatre (ou cinq) roues, donc class Automobile { Roue roues[5]; ... } * Un segment comporte deux points; * Un anneau est un cas particulier d'un cercle; * Une forme contient un rectangle englobant: class Shape { Rect r; ... } * Un triangle est une forme particulire: class Triangle : public Shape { ... } Discussion : un carr est-il un cas particulier d'un rectangle ?

Accs aux donnes et mthodes


Les attributs de la classe de base peuvent tre dsigns directement ou par le nom de la classe de base, en employant l'oprateur de porte :: class DescrHabitant { string nom; string domicile; public: DescrHabitant(); void show(); }; class DescrResidence : public DescrHabitant { string residence; public: DescrResidence(); void show(); };

Implantations
DescrHabitant::DescrHabitant() { cout << "Entrez votre nom : "; cin >> nom; cout << "Entrez votre domicile : "; cin >> domicile; } void DescrHabitant::show() { cout << "Nom: \t\t" << nom << endl; cout << "Domicile \t" << domicile << endl; } DescrResidence::DescrResidence() { // appel implicite du constructeur par dfaut de la classe de base. cout << "Entrez votre residence : "; cin >> residence; } void DescrResidence::show() { DescrHabitant::show(); // l'appel de la mthode de la classe de base. cout << "Residence \t" << residence << endl;

Hritage multiple
Une classe peut hriter de plusieurs classes. Les classes de bases sont alors numres dans la dfinition. class D : public B1, public B2 {...}