Classes en C++ C++... · 2005. 4. 5. · Classes en C++ 2ème partiepartie Yacine BELLIK IUT...
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