Classes en C++ C++... · 2005. 4. 5. · Classes en C++ 2ème partiepartie Yacine BELLIK IUT...

38
1 Classes en C++ Classes en C++ 2 2 è me me partie partie Yacine BELLIK Yacine BELLIK IUT d IUT d’ Orsay Orsay Universit Université Paris XI Paris XI Algorithmique/Langage 1ère année Yacine.Bellik@iut Yacine.Bellik@iut-orsay.fr orsay.fr 2 Plan du cours Plan du cours Surd Surdéfinition finition des op des opérateurs rateurs Surd Surdéfinition finition des op des opérateurs qui modifient l rateurs qui modifient l’ objet cible objet cible Constructeur par recopie et op Constructeur par recopie et opérateur d rateur d’ affectation affectation Objets membres Objets membres Conversions Conversions Tableau d Tableau d’ objets objets Objets constants Objets constants Exemple de conception d Exemple de conception d ’ une classe une classe Donn Données membres statiques es membres statiques thodes statiques thodes statiques Variables locales statiques Variables locales statiques

Transcript of Classes en C++ C++... · 2005. 4. 5. · Classes en C++ 2ème partiepartie Yacine BELLIK IUT...

1

Classes en C++Classes en C++22èèmeme partiepartie

Yacine BELLIKYacine BELLIK

IUT dIUT d’’OrsayOrsayUniversitUniversitéé Paris XIParis XI

Algorithmique/Langage1ère année

[email protected]@iut--orsay.frorsay.fr 22

Plan du coursPlan du cours

SurdSurdééfinitionfinition des opdes opéérateursrateursSurdSurdééfinitionfinition des opdes opéérateurs qui modifient lrateurs qui modifient l’’objet cibleobjet cibleConstructeur par recopie et opConstructeur par recopie et opéérateur drateur d’’affectationaffectationObjets membresObjets membresConversionsConversionsTableau dTableau d’’objetsobjetsObjets constantsObjets constantsExemple de conception dExemple de conception d ’’une classeune classeDonnDonnéées membres statiqueses membres statiquesMMééthodes statiquesthodes statiquesVariables locales statiquesVariables locales statiques

2

[email protected]@iut--orsay.frorsay.fr 33

SurdSurdééfinitionfinition des opdes opéérateursrateurs

Un opUn opéérateur peut srateur peut s’’appliquer appliquer àà diffdifféérents typesrents types–– ExempleExemple

Division entiDivision entièère (entier/re (entier/entierentier))Division rDivision rééelle (relle (rééel/el/rrééelel ou rou rééel/entier ou entier/el/entier ou entier/rereééll))

Le langage C++ permet de Le langage C++ permet de surdsurdééfinirfinir les oples opéérateurs rateurs existants pour les nouveaux types dexistants pour les nouveaux types dééfinis par lfinis par l’’utilisateurutilisateur–– ExempleExemple

Addition de vecteursAddition de vecteursAddition de matricesAddition de matricesAddition de nombres complexesAddition de nombres complexesAddition de pointsAddition de pointsEtc.Etc.

[email protected]@iut--orsay.frorsay.fr 44

Exemple : addition de 2 points Exemple : addition de 2 points sans usage dsans usage d’’opopéérateursrateurs

Point.hPoint.hclass Pointclass Point{{

intint __x,_yx,_y;;public:public:

......Point addition (const Point &) const;Point addition (const Point &) const;

};};

Point Point Point::additionPoint::addition (const Point & p) const(const Point & p) const{{

Point Point resres;;res._x = _x + res._x = _x + p._xp._x;;res._y = _y + res._y = _y + p._yp._y;;return return resres;;

}}

Point.CPoint.C

return Point(_x+p._x ,_y+p._y );

3

[email protected]@iut--orsay.frorsay.fr 55

UtilisationUtilisation

Prog.CProg.C

#include <iostream.h>#include “Point.h”

void main(){

Point p1(1,2), p2(3,4), p3(5,6), p4, p5;p4 = p1.addition(p2);p5 = (p1.addition(p2)).addition(p3);cout << "p4 = p1 + p2\n"; p4.afficher();cout << "p5 = p1 + p2 + p3\n"; p5.afficher();

}

[email protected]@iut--orsay.frorsay.fr 66

Exemple : addition de 2 points Exemple : addition de 2 points avec usage davec usage d’’opopéérateursrateurs

Point.hPoint.hclass Pointclass Point{{

intint __x,_yx,_y;;public:public:

......Point operator+ (const Point &) const;Point operator+ (const Point &) const;

};};

Point Point Point::operatorPoint::operator+ (const Point & p) const+ (const Point & p) const{{

Point Point resres;;res._x = _x + res._x = _x + p._xp._x;;res._y = _y + res._y = _y + p._yp._y;;return return resres;;

}}

Point.CPoint.C

return Point( _x+p._x , _y+p._y );

4

[email protected]@iut--orsay.frorsay.fr 77

UtilisationUtilisation

Prog.CProg.C#include “Point.h”

void main(){

Point p1(1,2), p2(3,4), p3(5,6), p4a, p4b, p5a, p5b;p4a = p1.operator+(p2);p4b = p1+p2;p5a = (p1.operator+(p2)).operator+(p3);p5b = p1+p2+p3;

}

On voit que la notation utilisOn voit que la notation utiliséée pour p4b et p5b est beaucoup plus pratique que celle e pour p4b et p5b est beaucoup plus pratique que celle utilisutiliséée pour p4a et p5ae pour p4a et p5aIl est important de noter que dans lIl est important de noter que dans l’’expression p1+p2expression p1+p2

– L’opérande de gauche p1 correspond à l’objet cible de la méthode operator+– L’opérande de droite p2 correspond au paramètre explicite p de la méthode operator +

[email protected]@iut--orsay.frorsay.fr 88

Addition dAddition d’’un point et dun point et d’’un entierun entier

La mLa mééthode prthode prééccéédente nous permet de faire la somme de 2 points (p1+p2)dente nous permet de faire la somme de 2 points (p1+p2)Mais que faire si on veut aussi pouvoir effectuer la somme dMais que faire si on veut aussi pouvoir effectuer la somme d’’un point et dun point et d’’un un entier (p1+5) ?entier (p1+5) ?2 solutions possibles :2 solutions possibles :

1.1. Fournir un moyen au compilateur de convertir un entier en un poiFournir un moyen au compilateur de convertir un entier en un pointntSoit en Soit en éécrivant un constructeur crivant un constructeur àà un paramun paramèètre entiertre entierSoit en Soit en éécrivant un constructeur crivant un constructeur àà 2 param2 paramèètres entiers mais avec au moins une valeur tres entiers mais avec au moins une valeur par dpar dééfaut pour le second paramfaut pour le second paramèètretre

2.2. EcrireEcrire une mune mééthode thode operatoroperator+ prenant comme param+ prenant comme paramèètre explicite un entiertre explicite un entier

Point Point Point::operatorPoint::operator+ (+ (intint n) constn) const{{

Point Point resres;;

res._x = _x + n;res._x = _x + n;

res._y = _y + 0;res._y = _y + 0;

return return resres;;}}

return Point( _x+n , _y );

5

[email protected]@iut--orsay.frorsay.fr 99

Addition dAddition d’’un entier et dun entier et d’’un pointun point

Les mLes mééthodes prthodes prééccéédentes nous permettent de faire la somme de 2 dentes nous permettent de faire la somme de 2 points (p1+p2) ou dpoints (p1+p2) ou d’’un point et dun point et d’’un entier (p1+5) un entier (p1+5) Mais que faire si on veut aussi pouvoir effectuer la somme dMais que faire si on veut aussi pouvoir effectuer la somme d’’un un entier et dentier et d’’un point (5+p1) ?un point (5+p1) ?

SS’’il fallait il fallait éécrire une mcrire une mééthode pour 5+p1, 5 serait lthode pour 5+p1, 5 serait l’’objet cible et p1 le objet cible et p1 le paramparamèètre explicitetre explicite–– Cela impliquerait que la mCela impliquerait que la mééthode en question doit être rajoutthode en question doit être rajoutéée aux e aux

entiersentiers–– Il faudrait donc modifier le code source du compilateur. Cette sIl faudrait donc modifier le code source du compilateur. Cette solution olution

nn’’est donc pas possibleest donc pas possible

Solution : Solution : éécrire une fonction externecrire une fonction externe–– Cette fonction aura 2 paramCette fonction aura 2 paramèètres explicites (cette fonction tres explicites (cette fonction éétant externe, tant externe,

il nil n’’y a plus dy a plus d’’objet cible)objet cible)–– Le premier paramLe premier paramèètre (optre (opéérande de gauche) doit être un entierrande de gauche) doit être un entier–– Le second paramLe second paramèètre (optre (opéérande de droite) doit être un pointrande de droite) doit être un point

[email protected]@iut--orsay.frorsay.fr 1010

Addition dAddition d’’un entier et dun entier et d’’un pointun point

Fonction externeFonction externe

Point operator+ (Point operator+ (intint n, const Point & p)n, const Point & p){{

intint x = n + x = n + p.getAbsp.getAbs();();

intint y = p.getOrd();y = p.getOrd();Point Point resres(x,y);(x,y);

return return resres;;

}}

EtantEtant dans une fonction externe, on ndans une fonction externe, on n’’a pas acca pas accèès aux s aux donndonnéées prives privéées de la classe Point des de la classe Point d’’ooùù ll’’utilisation des utilisation des accesseurs publiques accesseurs publiques getAbsgetAbs() et () et getOrdgetOrd()()

return Point(n+p.getAbs(),p.getOrd());

6

[email protected]@iut--orsay.frorsay.fr 1111

Autre solutionAutre solution

On peut couvrir les 3 casOn peut couvrir les 3 cas–– Point + Point + PointPoint–– Point + EntierPoint + Entier–– Entier + PointEntier + Point

grâce grâce àà ::–– Un Un constructeurconstructeur àà partirpartir dd’’un un entierentier–– La fonction externe suivante :La fonction externe suivante :

Point operator+ (const Point & p1, const Point & p2)Point operator+ (const Point & p1, const Point & p2){{

intint x=p1.getAbs()+p2.getAbs();x=p1.getAbs()+p2.getAbs();intint y=p1.getOrd()+p2.getOrd();y=p1.getOrd()+p2.getOrd();Point Point resres(x,y);(x,y);return return resres;;

}}

return Point(p1.getAbs()+p2.getAbs(),

p1.getOrd()+p2.getOrd());

[email protected]@iut--orsay.frorsay.fr 1212

RRéécapitulatifcapitulatif

3 3 cascas àà couvrircouvrir–– Point + PointPoint + Point–– Point + Point + EntierEntier–– EntierEntier + Point+ Point

Solution 1Solution 1–– Point + Point : Point + Point : MMééthodethode Point Point Point::operatorPoint::operator+ (const Point& p) const+ (const Point& p) const–– Point + Point + EntierEntier : : MMééthodethode Point Point Point::operatorPoint::operator+ (+ (intint n) constn) const–– EntierEntier+ Point : + Point : FonctionFonction externeexterne Point operator+ (Point operator+ (intint n, const Point & p)n, const Point & p)

Solution 2Solution 2–– Point + Point : Point + Point : MMééthodethode Point Point Point::operatorPoint::operator+ (const Point& p) const+ (const Point& p) const–– Point + Point + EntierEntier : : ConstructeurConstructeur àà partirpartir dd’’un un entierentier–– EntierEntier+ Point : + Point : FonctionFonction externeexterne Point operator+ (Point operator+ (intint n, const Point & p)n, const Point & p)

Solution 3Solution 3–– Point + Point : Point + Point : FonctionFonction externeexterne Point operator+ (const Point & p1, Point operator+ (const Point & p1,

const Point & p2)const Point & p2)–– Point + Point + EntierEntier ouou EntierEntier + Point : + Point : ConstructeurConstructeur àà partirpartir dd’’un un entierentier

7

[email protected]@iut--orsay.frorsay.fr 1313

SurdSurdééfinitionfinition de lde l’’opopéérateur <<rateur <<

coutcout << "bonjour";<< "bonjour";coutcout n'est pas une instruction mais un objet ! n'est pas une instruction mais un objet ! (de la classe (de la classe ostreamostream du langage C++)du langage C++)Pour pouvoir Pour pouvoir éécrire crire coutcout << p1 (p1 << p1 (p1 éétant un Point)tant un Point)

–– il faudrait rajouter la mil faudrait rajouter la mééthode suivante thode suivante àà la classe la classe ostreamostream ::ostreamostream& & ostreamostream::::operatoroperator<< (<< (constconst Point &) ;Point &) ;

–– il faudrait donc modifier le code source du compilateur, ce qui il faudrait donc modifier le code source du compilateur, ce qui n'est pas possiblen'est pas possibleSolution : écrire la fonction externe suivante :

ostream & operator << (ostream & o , const Point & p){

o << "abscisse : " << p.getAbs()<<endl;o << "ordonnée : " << p.getOrd()<<endl;return o;

}

On retourne l'objet o passOn retourne l'objet o passéé en paramen paramèètre afin de pouvoir enchatre afin de pouvoir enchaîîner ner plusieurs affichages : plusieurs affichages : coutcout<<p1<<p2<<p3;<<p1<<p2<<p3;

[email protected]@iut--orsay.frorsay.fr 1414

SurdSurdééfinitionfinition de lde l’’opopéérateur >>rateur >>

cincin >> x;>> x;cincin n'est pas une instruction mais un objet ! n'est pas une instruction mais un objet ! (de la classe (de la classe istreamistream du langage C++)du langage C++)Pour pouvoir Pour pouvoir éécrire crire cincin >> p1 (p1 >> p1 (p1 éétant un Point)tant un Point)

–– il faudrait rajouter la mil faudrait rajouter la mééthode suivante thode suivante àà la classe la classe istreamistreamistreamistream& & istreamistream::::operatoroperator>> (Point &) ;>> (Point &) ;

–– il faudrait donc modifier le code source du compilateur, ce qui il faudrait donc modifier le code source du compilateur, ce qui n'est pas possiblen'est pas possibleSolution : écrire la fonction externe suivante :

istream & operator >> (istream & i , Point & p){ int n;

cout<< "Entrez l'abscisse : "; i>>n; p.setAbs(n);cout<< "Entrez l'ordonnée : "; i>>n; p.setOrd(n);return i;

}

On retourne l'objet i passOn retourne l'objet i passéé en paramen paramèètre afin de pouvoir enchatre afin de pouvoir enchaîîner ner plusieurs saisies : plusieurs saisies : cincin>>p1>>p2>>p3;>>p1>>p2>>p3;

8

[email protected]@iut--orsay.frorsay.fr 1515

Les fonctions amiesLes fonctions amiesUne fonction amie d'une classe est une fonction externe qui peutUne fonction amie d'une classe est une fonction externe qui peut accaccééder aux donnder aux donnéées es privprivéées de la classe (en lecture et en es de la classe (en lecture et en éécriture).criture).Elle Elle doitdoit êtreêtre ddééclarclarééee àà l'intl'intéérieurrieur de la de la classeclasse dontdont elleelle estest l'amiel'amie, , prprééccééddééee dudu mot mot clclééfriend

class Point{

int _x,_y;public:...friend istream & operator >> (istream & i , Point & p);

};

istream & operator >> (istream & i , Point & p){ int n;

cout<< "Entrez l'abscisse : "; i>>p._x;cout<< "Entrez l'ordonnée : "; i>>p._y;return i;

}

Attention: Les fonctions amies facilitent l'écriture mais leur existence viole le principe d'encapsulation des données : minimiser leur usage (surdéfinition d'opérateurs)

SurdSurdééfinitionfinition des opdes opéérateurs qui rateurs qui modifient lmodifient l ’’objet cibleobjet cible

++ , ++ , ---- , += , *= , etc., += , *= , etc.

9

[email protected]@iut--orsay.frorsay.fr 1717

Notions prNotions prééalablesalables

thisthis : adresse de l: adresse de l’’objet cibleobjet cible**thisthis : objet cible lui: objet cible lui--mêmemêmeEquivalenceEquivalence ALGO / C++ALGO / C++–– ALGOALGO

cible.membrecible.membre

–– C++C++membremembre*this.membre*this.membrethisthis --> membre> membre

[email protected]@iut--orsay.frorsay.fr 1818

La classe DateLa classe Date

DonnDonnéées qui caractes qui caractéérisent une date risent une date

Le jourLe jourLe moisLe moisLL ’’annannééee

DonnDonnéées prives privééeses

10

[email protected]@iut--orsay.frorsay.fr 1919

Exemple de lExemple de l ’’opopéérateur ++rateur ++pour la classe Datepour la classe Date

Passer au lendemain : opPasser au lendemain : opéérateur ++ rateur ++

voidvoid Date::Date::operatoroperator ++ ( ) {++ ( ) {……}; };

ou ou Date Date Date::Date::operatoroperator ++ ( ) {++ ( ) {……}; };

ou ou Date & Date::Date & Date::operatoroperator ++ ( ) {++ ( ) {……};};

Quelle est la meilleure solution ?Quelle est la meilleure solution ?

Pas de const car on modifie l ’objet cible

[email protected]@iut--orsay.frorsay.fr 2020

Exemple de lExemple de l ’’opopéérateur ++rateur ++pour la classe Datepour la classe Date

Avec cette solution on ne peut pas utiliser lAvec cette solution on ne peut pas utiliser l’’opopéérateur ++ dans rateur ++ dans une expression telle que :une expression telle que :

d1 = 5 + (++d2) d1 = 5 + (++d2) …… ouou if ( d1 == (++d2) ) if ( d1 == (++d2) ) ……

void Date::operator ++ ( ){

_jour++;if (_jour>nbJoursMois()){

_jour=1; _mois++;if (_mois>12){

_mois=1; _annee++;}

}return;

};

11

[email protected]@iut--orsay.frorsay.fr 2121

Exemple de lExemple de l ’’opopéérateur ++rateur ++pour la classe Datepour la classe Date

Maintenant on peut utiliser l’opérateur ++ dans une expression mais l’enchaînement de ++ plusieurs fois ne donne pas le bon résultat.Si on écrit ++ (++ d), on s’attend à ce que la date cible passe au surlendemain. Or, ce sera la copie de la date cible renvoyée qui contiendra la date du surlendemain et non la date cible elle-même.

Date Date::operator ++ ( ){

_jour++;if (_jour>nbJoursMois()){

_jour=1; _mois++;if (_mois>12){

_mois=1; _annee++;}

}return Date (_jour,_mois,_annee);

};

[email protected]@iut--orsay.frorsay.fr 2222

Exemple de lExemple de l ’’opopéérateur ++rateur ++pour la classe Datepour la classe Date

Cette solution est la plus correcte. Elle renvoie une r. Elle renvoie une rééfféérence rence àà ll’’objet objet cible luicible lui--même. même. On peut utiliser lOn peut utiliser l’’opopéérateur ++ dans une expression.rateur ++ dans une expression.LL’’enchaenchaîînement de ++ plusieurs fois donne le bon rnement de ++ plusieurs fois donne le bon réésultat.sultat.Si on Si on éécrit ++ (++ d), la date cible passe au surlendemain.crit ++ (++ d), la date cible passe au surlendemain.

Date & Date::operator ++ ( ){

_jour++;if (_jour>nbJoursMois()){

_jour=1; _mois++;if (_mois>12){

_mois=1; _annee++;}

}return *this;

};

12

[email protected]@iut--orsay.frorsay.fr 2323

Position de lPosition de l ’’opopéérateur ++ :rateur ++ :prprééfixfixéée ou e ou postfixpostfixééee ??

Comment faire la diffComment faire la difféérence entre ++d et d++ ?rence entre ++d et d++ ?

La mLa mééthode suivante est appelthode suivante est appeléée pour ++d (pre pour ++d (prééfixfixéée) :e) :

Date & Date::operator ++ ( ){

…};

La mLa mééthode suivante est appelthode suivante est appeléée pour d++ (e pour d++ (postfixpostfixééee) :) :

Date Date::operator ++ ( int n){

…};

Le paramLe paramèètre n sert juste tre n sert juste àà distinguer les 2 cas.distinguer les 2 cas.

Constructeur par recopie et Constructeur par recopie et opopéérateur drateur d’’affectationaffectation

13

[email protected]@iut--orsay.frorsay.fr 2525

Constructeur par recopieConstructeur par recopie

class Point {

public : Point (int a, int b); Point (const Point & p);

private : int _x, _y;

};

Point p1(2,3);Point p2=p1;Point p3(p2);

Passage par rPassage par rééfféérence obligatoirerence obligatoire

[email protected]@iut--orsay.frorsay.fr 2626

Constructeur par recopieConstructeur par recopie

Le constructeur pas recopie est Le constructeur pas recopie est éégalement utilisgalement utiliséé lors lors des passages de paramdes passages de paramèètres par valeurtres par valeur

Si le dSi le dééveloppeur nveloppeur n ’’a pas pra pas préévu de constructeur par vu de constructeur par recopie, le compilateur utilise un constructeur par recopie, le compilateur utilise un constructeur par recopie par drecopie par dééfaut qui ne fait que recopier les donnfaut qui ne fait que recopier les donnéées es membres.membres.

Le constructeur par recopie doit être redLe constructeur par recopie doit être redééfini lorsque la fini lorsque la copie dcopie d ’’un objet implique un traitement diffun objet implique un traitement difféérent de la rent de la simple recopie des donnsimple recopie des donnééeses

14

[email protected]@iut--orsay.frorsay.fr 2727

OpOpéérateur drateur d’’affectationaffectation

class Point {

public : Point (int a=0, int b=0);Point (const Point & p);Point operator = (const Point & p);

private : int _x, _y;

};Point p1(2,3);Point p2;p2=p1; // <=> p2.operator=(p1); Appel de l ’opérateur d’affectation

[email protected]@iut--orsay.frorsay.fr 2828

OpOpéérateur drateur d’’affectationaffectation

Si le dSi le dééveloppeur nveloppeur n ’’a pas pra pas préévu dvu d ’’opopéérateur drateur d ’’affectation, le affectation, le

compilateur utilise un opcompilateur utilise un opéérateur drateur d ’’affectation par daffectation par dééfaut qui ne fait que faut qui ne fait que

recopier les donnrecopier les donnéées membres.es membres.

LL ’’opopéérateur drateur d ’’affectation doit être redaffectation doit être redééfini lorsque lfini lorsque l ’’affectation daffectation d ’’un un

objet implique un traitement diffobjet implique un traitement difféérent de la simple recopie des donnrent de la simple recopie des donnéées.es.

En gEn géénnééral, la redral, la redééfinition du constructeur par recopie implique celle de finition du constructeur par recopie implique celle de

ll ’’opopéérateur drateur d ’’affectation et inversementaffectation et inversement

Faire attention aux cas oFaire attention aux cas oùù il sil s ’’agit du même objet ( P1=P1)agit du même objet ( P1=P1)

Attention : Il nAttention : Il n ’’y a pas de dy a pas de dééfinition par dfinition par dééfaut pour les opfaut pour les opéérateurs de rateurs de

comparaison ( == , != , < , > , <= , >= )comparaison ( == , != , < , > , <= , >= )

15

[email protected]@iut--orsay.frorsay.fr 2929

Objets temporaires, constructeur par Objets temporaires, constructeur par recopie et oprecopie et opéérateur drateur d’’affectationaffectationclass Point {public :

Point (int a=0, int b=0);void changeCoordonnees (int a, int b);

private : int _x, _y;

};

Point p1;p1=Point (2,3); // 1. Construction d ’un objet temporaire Point(2,3)

// 2. Appel de l’opérateur d’affectation en lui passant comme paramètrel ’objet temporaire créé

Point p2=p1; //Appel du constructeur par recopie en lui passant comme paramètre l ’objet p1

Point p3;p3=p1; //Appel de l ’opérateur d ’affectation en lui passant comme paramètre l ’objet p1

ExceptionPoint p=Point(2,3); <=> Point p(2,3);

pas d’objet temporaire, pas d ’appel du constructeur de recopie

[email protected]@iut--orsay.frorsay.fr 3030

Construction des objets membresConstruction des objets membres

Les objets membres sont construits avant lLes objets membres sont construits avant l ’’objet objet principal grâce au constructeur sans paramprincipal grâce au constructeur sans paramèètrestres

class Point {public : Point ( );

Point (int a, int b);void changeCoordonnees (int a, int b);

private : int _x, _y;};

class Rectangle {public : Rectangle (int x1, int y1, int x2, int y2);

private : Point _p1,_p2;};

Rectangle::Rectangle (int x1, int y1, int x2, int y2){_p1.changeCoordonnees(x1,y1); _p2.changeCoordonnees(x2,y2);

}

Rectangle r(10,20,30,40);

16

[email protected]@iut--orsay.frorsay.fr 3131

Construction des objets membresConstruction des objets membres

Les objets membres sont construits avant lLes objets membres sont construits avant l ’’objet objet principal grâce aux valeurs par dprincipal grâce aux valeurs par dééfautfaut

class Point {public :

Point (int a=0, int b=0);void changeCoordonnees (int a, int b);

private : int _x, _y;

};

class Rectangle {public :

Rectangle (int x1, int y1, int x2, int y2);private :

Point _p1,_p2;};

Rectangle::Rectangle (int x1, int y1, int x2, int y2){_p1.changeCoordonnees(x1,y1); _p2.changeCoordonnees(x2,y2);

}

Rectangle r(10,20,30,40);

[email protected]@iut--orsay.frorsay.fr 3232

Construction des objets membres: Construction des objets membres: problproblèèmeme

Pas de constructeur sans paramPas de constructeur sans paramèètres et pas de tres et pas de valeurs par dvaleurs par dééfaut : problfaut : problèème !!!me !!!

class Point {public :

Point (int a, int b);void changeCoordonnees (int a, int b);

private : int _x, _y;

};

class Rectangle {public :

Rectangle (int x1, int y1, int x2, int y2);private :

Point _p1,_p2;};

Rectangle::Rectangle (int x1, int y1, int x2, int y2){_p1.changeCoordonnees(x1,y1); _p2.changeCoordonnees(x2,y2);

}

Rectangle r(10,20,30,40);

17

[email protected]@iut--orsay.frorsay.fr 3333

Construction des objets membres: Construction des objets membres: solutionsolution

Solution : construction des objets Point juste avant la Solution : construction des objets Point juste avant la construction de lconstruction de l ’’objet Rectangleobjet Rectangle

class Point {public :

Point (int a, int b);void changeCoordonnees (int a, int b);

private : int _x, _y;

};

class Rectangle {public :

Rectangle (int x1, int y1, int x2, int y2);private :

Point _p1,_p2;};

Rectangle::Rectangle(int x1,int y1,int x2,int y2):_p1(x1,y1),_p2(x2,y2){... }

Rectangle r(10,20,30,40);

Les conversionsLes conversions

18

[email protected]@iut--orsay.frorsay.fr 3535

Constructeur sans paramConstructeur sans paramèètres ou tres ou valeurs par dvaleurs par dééfaut ?faut ?

Que choisir ?Que choisir ?

class Point {public :

Point ( );Point (int a, int b);

private : int _x, _y;

};Point p1; Point p2(10,20);

OUclass Point {public :

Point (int a=0, int b=0);private :

int _x, _y;};Point p1; Point p2(10,20); Point p3(10);

[email protected]@iut--orsay.frorsay.fr 3636

Attention : Valeurs par dAttention : Valeurs par dééfaut => faut => Conversions implicitesConversions implicites

La prLa préésence dsence d ’’un constructeur un constructeur àà un seul paramun seul paramèètre fournit une tre fournit une conversion implicite du type de ce paramconversion implicite du type de ce paramèètre vers la classe.tre vers la classe.

class Point {public :

Point (int a=0, int b=0);Point operator + (const Point & p) const;

private : int _x, _y;

};

Point p(10) => construit un objet Point (10,0);

L’opérateur + a été surdéfini pour 2 points :

Point p1(4,5), p2(8,9);

p1+p2 sera accepté

mais aussi p1+20 !!!

19

[email protected]@iut--orsay.frorsay.fr 3737

Solution : une bonne conceptionSolution : une bonne conception

Savoir programmer en C++ ne signifie pas savoir programmer en Savoir programmer en C++ ne signifie pas savoir programmer en

orientorientéé--objetobjet

RRééflflééchir au sens des constructions (que signifie construire un pointchir au sens des constructions (que signifie construire un point

àà partir dpartir d ’’un entier ?)un entier ?)

RRééflflééchir au sens des conversions (que signifie convertir un entier chir au sens des conversions (que signifie convertir un entier

en un point ?)en un point ?)

Ne pas autoriser des construction ou des conversion qui nNe pas autoriser des construction ou des conversion qui n ’’ont pas ont pas

un sens un sens «« éévidentvident »» ou qui ont un sens ambigu ou qui ont un sens ambigu

[email protected]@iut--orsay.frorsay.fr 3838

Exemple : la classe MatriceExemple : la classe Matrice

Attention aux conversions implicitesAttention aux conversions implicites

class Matrice {public :

Matrice (int l=1, int c=1);Matrice operator + (const Matrice & m) const;

private : int _nblignes, _nbcolonnes;int _tab [MAX][MAX] ;

};

Matrice m1(8); // crée une matrice (8,1)Matrice m2(8,1);Matrice m3(8,1);

m3=m1+m2; //OK

mais attention !

m3=m1+8; // fait la somme de m1 et d’une matrice temporaire (8,1)

Pourtant l’opérateur + n’a pas été surdéfini pour une matrice et un entier !!!

20

[email protected]@iut--orsay.frorsay.fr 3939

Exemple : la classe MatriceExemple : la classe Matrice

Les opLes opéérateurs rateurs surdsurdééfinisfinis sont prioritaires par rapport sont prioritaires par rapport aux conversions implicitesaux conversions implicites

class Matrice {public :

Matrice (int l=1, int c=1);Matrice operator + (const Matrice & m) const;Matrice operator + (int x) const;

private : int _nblignes, _nbcolonnes;int _tab[MAX][MAX] ;

};

Matrice m1(8); // crée une matrice (8,1)Matrice m2(8,1);Matrice m3(8,1);

m3=m1+m2; //OK

m3=m1+8; // appel de l’opérateur surdéfini: pas de conversion implicite

[email protected]@iut--orsay.frorsay.fr 4040

Conversion dConversion d ’’un type de base en un type de base en un type de classeun type de classe

Soit une classe ASoit une classe AEcrire un constructeur pour la classe A qui prend comme paramEcrire un constructeur pour la classe A qui prend comme paramèètre tre un paramun paramèètre ayant un type de base (char, tre ayant un type de base (char, intint, , floatfloat, double, ...) , double, ...) => => ddééfinition dfinition d ’’une conversion de ce type de base vers Aune conversion de ce type de base vers A

class Point {

public : Point (int a); // conversion d ’un entier en pointPoint (double a); // conversion d ’un double en pointPoint (int a, int b);

private : int _x, _y;

};

21

[email protected]@iut--orsay.frorsay.fr 4141

Conversion dConversion d’’un type de classe en un type de classe en un type de baseun type de base

On ne spOn ne spéécifie pas le type retourncifie pas le type retournéé pour les oppour les opéérateurs de rateurs de conversion (le nom de lconversion (le nom de l ’’opopéérateur lrateur l ’’indique)indique)

class Point {

public : Point (int a, int b);

operator int(); //conversion d’un point en entier//doit retourner un entier

operator double();//conversion d’un point en double//doit retourner un double

private : int _x, _y;

};

[email protected]@iut--orsay.frorsay.fr 4242

Conversion entre classes : Conversion entre classes : 11èère mre mééthodethode

Soit une classe A et une classe BSoit une classe A et une classe B

Ecrire un constructeur pour la classe A qui prend comme paramEcrire un constructeur pour la classe A qui prend comme paramèètre tre un objet de la classe B un objet de la classe B => => ddééfinition dfinition d ’’une conversion de B vers Aune conversion de B vers A

Ecrire un constructeur pour la classe B qui prend comme paramEcrire un constructeur pour la classe B qui prend comme paramèètre tre un objet de la classe A un objet de la classe A => => ddééfinition dfinition d ’’une conversion de A vers Bune conversion de A vers B

22

[email protected]@iut--orsay.frorsay.fr 4343

Conversion entre classes : Conversion entre classes : 22èème mme mééthodethode

Soit une classe A et une classe BSoit une classe A et une classe B

DDééfinition de lfinition de l ’’opopéérateur rateur operatoroperator AA ( )( ) dans la classe B dans la classe B => => ddééfinition dfinition d ’’une conversion de B vers Aune conversion de B vers A

DDééfinition de lfinition de l ’’opopéérateur rateur operatoroperator B ( )B ( ) dans la classe A dans la classe A => => ddééfinition dfinition d ’’une conversion de A vers Bune conversion de A vers B

On nOn n ’’indique pas le type retournindique pas le type retournéé pour ces oppour ces opéérateurs car le nom rateurs car le nom de lde l ’’opopéérateur lrateur l ’’indiqueindique

[email protected]@iut--orsay.frorsay.fr 4444

ConseilsConseils

Ne pas abuser des conversionsNe pas abuser des conversions

Affecter un sens naturel aux constructeurs et Affecter un sens naturel aux constructeurs et aux opaux opéérateurs rateurs surdsurdééfinisfinis

Toujours suivre le Toujours suivre le «« bon sensbon sens »» et let l’é’évidencevidence

23

Tableau d'objetsTableau d'objets

[email protected]@iut--orsay.frorsay.fr 4646

Initialisation dInitialisation d’’un tableau dun tableau d’’objetsobjets

class Point {

public : Point (int a, int b);

private : int _x, _y;

};

Point courbe[50]; // incorrect car il n’y a pas de constructeur sans paramètres ou avec des valeurs par défaut

Point courbe[3]={Point(2,3),Point(7,5),Point(6,9)}; // OK

24

[email protected]@iut--orsay.frorsay.fr 4747

Initialisation dInitialisation d’’un tableau dun tableau d’’objetsobjets

class Point {

public : Point (int a=0, int b=0);

private : int _x, _y;

};

Point courbe[50]; // OK

MMééthodes et objets constantsthodes et objets constants

25

[email protected]@iut--orsay.frorsay.fr 4949

Objets constantsObjets constants

Une mUne mééthode dthode dééclarclaréée avec le qualificatif const e avec le qualificatif const ne modifie pas lne modifie pas l ’’objet cibleobjet cibleUn objet dUn objet dééclarclaréé avec le qualificatif const ne doit avec le qualificatif const ne doit pas pouvoir être modifipas pouvoir être modifiéé

Seules les mSeules les mééthodes const peuvent être thodes const peuvent être appelappeléées sur un objet constes sur un objet const

[email protected]@iut--orsay.frorsay.fr 5050

Objets constants : exempleObjets constants : exemple

class Point {

public : Point (int a, int b);void affiche( ) const;void changeCoordonnees(int a, int b);

private : int _x, _y;

};

Point p1(2,3);const Point p2(5,6);

p1.affiche(); //OKp2.affiche(); //OKp1.changeCoordonnees(7,8); //OK

p2.changeCoordonnees(4,9); // incorrect

26

Exemple de conception Exemple de conception dd’’une classeune classe

[email protected]@iut--orsay.frorsay.fr 5252

La classe DateLa classe Date

Quelles sont les donnQuelles sont les donnéées qui caractes qui caractéérisent risent une date ?une date ?

Le jourLe jourLe moisLe moisLL ’’annannééee

DonnDonnéées prives privééeses

27

[email protected]@iut--orsay.frorsay.fr 5353

La classe DateLa classe Date

class Date {class Date {

public :public :……………………

privateprivate ::intint _jour;_jour;intint _mois;_mois;intint _anne_annee;e;

}}

[email protected]@iut--orsay.frorsay.fr 5454

Constructeurs de la classe DateConstructeurs de la classe Date

Comment construire un objet Date ?Comment construire un objet Date ?Il faut 3 informations : le jour, le mois et lIl faut 3 informations : le jour, le mois et l ’’annannééee

constructeur constructeur àà 3 param3 paramèètrestresPeutPeut--on avoir des valeurs par don avoir des valeurs par dééfaut pour ces 3 paramfaut pour ces 3 paramèètres ?tres ?Non, mais si aucun paramNon, mais si aucun paramèètre ntre n ’’est fourni on peut initialiser la est fourni on peut initialiser la date date àà la date du jour la date du jour

constructeur sans paramconstructeur sans paramèètrestresOn peut construire une date On peut construire une date àà partir dpartir d ’’une autre date une autre date

inutile de redinutile de redééfinir le constructeur par recopie; celui parfinir le constructeur par recopie; celui parddééfaut convient bien faut convient bien

28

[email protected]@iut--orsay.frorsay.fr 5555

La classe DateLa classe Date

class Date {class Date {

public :public :Date ( ); Date ( );

Date (Date (intint j, j, intint m, m, intint a);a);

privateprivate ::intint _jour;_jour;intint _mois;_mois;intint _anne_annee;e;

}}

[email protected]@iut--orsay.frorsay.fr 5656

MMééthodes de la classe Datethodes de la classe Date

Quelles sont les opQuelles sont les opéérations qurations qu’’on peut faire sur on peut faire sur les dates ?les dates ?

Calculer le nombre de jours sCalculer le nombre de jours sééparant 2 datesparant 2 datesOpOpéérateur rateur -- entre 2 datesentre 2 dates

int Date::operator-(const Date& d) const {…};

29

[email protected]@iut--orsay.frorsay.fr 5757

MMééthodes de la classe Datethodes de la classe Date

Calculer une date passCalculer une date passéée ou futur e ou futur àà partir dpartir d ’’une date une date donndonnéée et de et d ’’un nombre de joursun nombre de jours

OpOpéérateur rateur -- entre une date et un entierentre une date et un entierDate Date::operator - (int nbJours) const {…};

OpOpéérateur + entre une date et un entierrateur + entre une date et un entierDate Date::operator + (int nbJours) const {…};

OpOpéérateur + entre un entier et une date ???rateur + entre un entier et une date ???Si méthode => Premier argument : objet cible

[email protected]@iut--orsay.frorsay.fr 5858

MMééthodes de la classe Datethodes de la classe Date

OpOpéérateur + entre un entier et une date: 4 possibilitrateur + entre un entier et une date: 4 possibilitééss

1. D1. Dééfinir une conversion entre nombre de jours et Datefinir une conversion entre nombre de jours et DateNon car Non car Pas de sens logique pour cette conversionPas de sens logique pour cette conversion

2. D2. Dééfinir une fonction amie : amie car besoin dfinir une fonction amie : amie car besoin d ’’accaccééder der àà jour, mois et jour, mois et anneeanneeNon car Non car Nuit aux principes de conception objetNuit aux principes de conception objet

3. D3. Dééfinir une fonction non amie mais rendre jour, mois et finir une fonction non amie mais rendre jour, mois et anneeannee en public en public (modification directe des donn(modification directe des donnéées possible)es possible)Non car Non car Nuit aux principes dNuit aux principes d ’’encapsulationencapsulation

4. D4. Dééfinir une fonction non amie mais fournir des mfinir une fonction non amie mais fournir des mééthodes publiques pour thodes publiques pour lire jour, mois et lire jour, mois et anneeanneeOui car Oui car AccAccèès aux donns aux donnéées seulement en lecture : meilleure solutiones seulement en lecture : meilleure solution

Date operator+ (int nbJours, const Date & d) {…};

30

[email protected]@iut--orsay.frorsay.fr 5959

La classe DateLa classe Date

class Date {class Date {public :public :

Date ( );Date ( );Date (Date (intint j, j, intint m, m, intint a);a);

intint lireJourlireJour ( ) ( ) constconst;;intint lireMoislireMois ( ) ( ) constconst;;intint lireAnneelireAnnee ( ) ( ) constconst;;intint operatoroperator -- ((constconst Date & d) Date & d) constconst; ; Date Date operatoroperator -- ((intint nbJoursnbJours) ) constconst;;Date Date operatoroperator + (+ (intint nbJoursnbJours) ) constconst;;

privateprivate ::intint _jour, _mois, _jour, _mois, _anne_annee;e;

}}Date Date operatoroperator + (+ (intint nbJoursnbJours, , constconst Date & d);Date & d);

[email protected]@iut--orsay.frorsay.fr 6060

MMééthodes de la classe Datethodes de la classe Date

DD’’autres opautres opéérations sur les dates ?rations sur les dates ?

Passer au lendemain : opPasser au lendemain : opéérateur ++ rateur ++ Date& Date& DateDate::::operatoroperator ++ ( ) {++ ( ) {……}; }; //pr//prééfixfixééDate Date::Date Date::operatoroperator ++ (++ (intint n ) {n ) {……}; }; ////postfixpostfixéé

Revenir Revenir àà la veille : opla veille : opéérateur rateur ----Date& Date& DateDate::::operatoroperator ---- ( ) {( ) {……}; }; //pr//prééfixfixééDate Date DateDate::::operatoroperator ---- ((intint n ) {n ) {……}; }; ////postfixpostfixéé

Avancer ou reculer de plusieurs jours : Avancer ou reculer de plusieurs jours : operateursoperateurs += et += et --==Date& Date::operator += (int nbJours ) {…}; Date& Date::operator -= (int nbJours ) {…};

31

[email protected]@iut--orsay.frorsay.fr 6161

MMééthodes de la classe Datethodes de la classe Date

DD ’’autres opautres opéérations sur les dates ?rations sur les dates ?Les comparaisons entre 2 datesLes comparaisons entre 2 dates== != > >= < <=== != > >= < <=int Date::operator == (const Date & d) const {…};

int Date::operator != (const Date & d) const {…};

int Date::operator > (const Date & d) const {…};

int Date::operator >= (const Date & d) const {…};

int Date::operator < (const Date & d) const {…};

int Date::operator <= (const Date & d) const {…};

[email protected]@iut--orsay.frorsay.fr 6262

MMééthodes de la classe Datethodes de la classe Date

DD ’’autres opautres opéérations sur les dates ?rations sur les dates ?Afficher et Saisir : opAfficher et Saisir : opéérateurs << et >>rateurs << et >>

ostream& operator << (ostream& out, const Date& d);

friend istream& operator >> (istream& in , Date& d);

Ces opCes opéérateurs doivent recevoir comme premier rateurs doivent recevoir comme premier argument un flot (argument un flot (coutcout, , cincin……) ce qui empêche d) ce qui empêche d’’en faire en faire des mdes mééthodes de la classe Datethodes de la classe DateIls doivent retourner ce même flot afin de pouvoir Ils doivent retourner ce même flot afin de pouvoir enchaenchaîîner ces opner ces opéérateurs (rateurs (coutcout<<date1<<date2)<<date1<<date2)

32

DonnDonnéées statiqueses statiques

[email protected]@iut--orsay.frorsay.fr 6464

MMééthodes de la classe Datethodes de la classe Date

DD ’’autres opautres opéérations sur les dates ?rations sur les dates ?Calculer le jour de semaine (Lundi, Mardi, etc.)Calculer le jour de semaine (Lundi, Mardi, etc.)

MMééthode qui renvoie un entier :thode qui renvoie un entier :1=lundi; 2=mardi; 3=mercredi; etc.1=lundi; 2=mardi; 3=mercredi; etc.

int Date::jourSemaine ( ) const {…};

Il serait intIl serait intééressant de disposer dressant de disposer d ’’un tableau de chaun tableau de chaîînes de nes de caractcaractèères contenant les mots res contenant les mots «« LundiLundi »», , «« MardiMardi »», , «« MercrediMercredi »», , etc.etc.

Il est inutile que ce tableau soit dupliquIl est inutile que ce tableau soit dupliquéé dans chaque objet dans chaque objet cc ’’est est une une donndonnééee dite dite statiquestatique

static char _tabJour[7][9];

33

[email protected]@iut--orsay.frorsay.fr 6565

DonnDonnéée statiquee statique

Une donnUne donnéée statique est une sorte de variable e statique est une sorte de variable globale encapsulglobale encapsuléée dans la classee dans la classe

d1._jourd1._moisd1._année

d2._jourd2._moisd2._année

_tabJour

Objet d1 Objet d2

[email protected]@iut--orsay.frorsay.fr 6666

DonnDonnéée statiquee statique

Une donnUne donnéée statique existe même si aucun e statique existe même si aucun objet de la classe nobjet de la classe n ’’a a ééttéé ddééclarclaréé

Elle doit être initialisElle doit être initialiséée au de au déébut du fichier .C but du fichier .C et non pas dans le fichier .het non pas dans le fichier .h

Si aucun objet nSi aucun objet n ’’a a ééttéé ddééclarclaréé, on peut y , on peut y accaccééder en prder en préécisant simplement le nom de la cisant simplement le nom de la classeclasse

34

MMééthodes statiquesthodes statiques

[email protected]@iut--orsay.frorsay.fr 6868

MMééthodes de la classe Datethodes de la classe Date

DD ’’autres opautres opéérations sur les dates ?rations sur les dates ?Quelle est la date dQuelle est la date d ’’aujourdaujourd ’’hui ?hui ?

MMééthode qui nthode qui n’’utilise pas lutilise pas l ’’objet cibleobjet cibleMMééthodethode qualifiqualifiéée de e de statiquestatique

static Date aujourdhui ( );

35

[email protected]@iut--orsay.frorsay.fr 6969

MMééthode statiquethode statique

CC ’’est une sorte de fonction indest une sorte de fonction indéépendante pendante encapsulencapsuléée dans la classee dans la classeCC ’’est une mest une mééthode qui nthode qui n’’utilise pas dutilise pas d’’objet cibleobjet cibleCC ’’est une mest une mééthode qui peut utiliser les donnthode qui peut utiliser les donnéées es statiques de la classestatiques de la classeCC ’’est une mest une mééthode qui peut être appelthode qui peut être appeléée même si e même si aucun objet de la classe naucun objet de la classe n ’’a a ééttéé ddééclarclarééDans ce cas lDans ce cas l’’appel se fait en prappel se fait en préécisant simplement le cisant simplement le nom de la classenom de la classeExemple dExemple d ’’appel :appel : cout << Date::aujourdhui ( );

[email protected]@iut--orsay.frorsay.fr 7070

DonnDonnéées et mes et mééthodes statiques : thodes statiques : exemple d'utilisationexemple d'utilisation

Compter le nombre d'objet créesclass Test {

private : static int _x;public : Test( ) {_x++;}

static void afficheNbObjets ( );};Fichier .C de la classeint Test::_x = 0;void Test:: afficheNbObjets( ) {

cout <<"il y a "<<_x<<" objets créés"<<endl;}Fichier .C principalvoid main ( ) {

Test::afficheNbObjets( ); // 0Test a; a.afficheNbObjets( ); // 1Test b; a.afficheNbObjets( ); // 2Test c; Test::afficheNbObjets( ); // 3

}

36

Variables locales statiquesVariables locales statiques

[email protected]@iut--orsay.frorsay.fr 7272

Variable locale statiqueVariable locale statique

Le qualificatif Le qualificatif staticstatic peut aussi speut aussi s ’’appliquer appliquer àà une une variable locale dvariable locale d ’’une fonction quelconqueune fonction quelconque

Une variable locale statique est une sorte de variable Une variable locale statique est une sorte de variable globale encapsulglobale encapsuléée au sein de la fonctione au sein de la fonction

Une variable locale statique est initialisUne variable locale statique est initialiséée par le e par le compilateur une seule foiscompilateur une seule fois

Une variable locale statique conserve sa valeur dUne variable locale statique conserve sa valeur d ’’un un appel de la fonction appel de la fonction àà un autreun autre

37

[email protected]@iut--orsay.frorsay.fr 7373

Variable locale statique: exempleVariable locale statique: exemple

Compter le nombre de fois quCompter le nombre de fois qu’’une fonction est une fonction est appelappeléée en utilisant une variable globalee en utilisant une variable globale

int compteur=0;...int f1 ( ) {

compteur++;cout << "Appel n° "<<compteur<<endl;return compteur;

}

Utilisation d'une variable globale : Utilisation d'une variable globale : mauvaise solutionmauvaise solutionLa variable globale peut être modifiLa variable globale peut être modifiéée par une autre e par une autre fonction (par erreur)fonction (par erreur)

[email protected]@iut--orsay.frorsay.fr 7474

Variable locale statique: exempleVariable locale statique: exemple

Compter le nombre de fois qu’une fonction est appelée en utilisant une variable locale statique

int f1 ( ) {

static int compteur=0;compteur++;cout << "Appel n° "<<compteur<<endl;return compteur;

}

L'intialisation se fera une seule fois, lors du premier appelLors des appels suivants, la variable garde la valeur qu'elle avait à la sortie de l'appel précédent

38

[email protected]@iut--orsay.frorsay.fr 7575

Variable locale statique: exempleVariable locale statique: exemple

void f1 ( ){

static bool premierAppel=true;

if (premierAppel) {

… // traitement premier appelpremierAppel=false;

} else {

… // traitement appels suivants}

}

RRééaliser un traitement particulier la premialiser un traitement particulier la premièère fois que re fois que la fonction est appella fonction est appeléée et un autre traitement les fois e et un autre traitement les fois suivantessuivantes