Vous êtes sur la page 1sur 69

Cours Langage C/C++ - Classes et objets Programmation Orient Objet

Thierry Vaira
BTS IRIS Avignon
tvaira@free.fr v0.1

Sommaire
1 2 3 4 5 6 7

Classes et objets Les objets constants Surcharge des oprateurs Lhritage Les exceptions Polymorphisme Transtypage

tv (BTS IRIS Avignon)

Cours C/C++

tvaira@free.fr

v0.1

2 / 69

Classes et objets

Classes et objets
Les classes sont les lments de base de la programmation oriente objet (POO) en C++. Dans une classe, on runit :
- des donnes variables : les donnes membres, ou les attributs de la classe. - des fonctions : les fonctions membres, ou les mthodes de la classe.

Une classe A apporte un nouveau type A ajout aux types (pr)dnis de base par C++. Une variable a cre partir du type de classe A est appele instance (ou objet) de la classe A. Exemple (non compilable*) :
class A; // dclare une classe A (* car elle nest pas dfinie) A a1; // instancie un objet a1 de type A A a2; // cre une instance a2 de type A

tv (BTS IRIS Avignon)

Cours C/C++

tvaira@free.fr

v0.1

3 / 69

Classes et objets

tat et comportement

Une classe se dclare dans un chier .h. La dclaration permet de connatre les types des choses constituant la classe, et ainsi de lutiliser. Une classe se dnit dans un chier .cc ou .cpp. La dnition permettra de fabriquer les choses constituant la classe. Un objet possdera une identit qui permet de distinguer un objet dun autre objet (son nom, une adresse mmoire). Un objet possdera un tat (les valeurs contenues dans les attributs propres cet objet). Un objet possdera un comportement (lutilisation de ses mthodes lui fera changer dtat).

tv (BTS IRIS Avignon)

Cours C/C++

tvaira@free.fr

v0.1

4 / 69

Classes et objets

Droits daccs aux membres (1/2)


Les droits daccs aux membres dune classe concernent aussi bien les mthodes que les attributs. En C++, on dispose des droits daccs suivants :
- Accs public : on peut utiliser le membre de nimporte o dans le programme. - Accs private : seule une fonction membre de la mme classe A peut utiliser ce membre ; il est invisible de lextrieur de A. - Accs protected : ce membre peut tre utilis par une fonction de cette mme classe A, et pas ailleurs dans le programme (ressemble donc private), mais il peut en plus tre utilis par une classe B qui hrite de A.

Il existe une rgle de POO qui prcise que les attributs doivent tre encapsules dans la classe pour viter une utilisation extrieure. Cest une forme de protection permettant dviter une utilisation incorrecte ou non prvue par le programmeur de la classe. On appliquera ce principe en dclarant lensemble des attributs en private.
tv (BTS IRIS Avignon) Cours C/C++ tvaira@free.fr v0.1 5 / 69

Classes et objets

Droits daccs aux membres (2/2)


Si cest ncessaire, laccs aux attributs privs dune classe se fera par lintermdiaire de mthodes nommes des accesseurs et manipulateurs. On a lhabitude de les nommer get() pour laccs en lecture et set() pour laccs en criture dun attribut. Exemple (non compilable car les mthodes ne sont pas dnies) :
class A { private: int x; // je suis un attribut priv de type int void foo(); // je suis une mthode prive de nom foo public: // seulement des mthodes ici (regle POO) int getX(); // je suis laccesseur get de x, je retourne sa valeur void setX(int); // je suis le manipulateur set de x, je fixe sa valeur void afficher(); // je suis une autre mthode publique };

tv (BTS IRIS Avignon)

Cours C/C++

tvaira@free.fr

v0.1

6 / 69

Classes et objets

Constructeur

Un constructeur est charg dinitialiser une instance (objet) de la classe. Il est appel automatiquement au moment de la cration de lobjet. Un constructeur est une mthode qui porte toujours le mme nom que la classe. Il existe quelques contraintes :
Il peut avoir des paramtres, et des valeurs par dfaut. Il peut y avoir plusieurs constructeurs pour une mme classe. Il na jamais de type de retour.

Il existe dautres constructeurs : le constructeur par dfaut et le constructeur de copie.

tv (BTS IRIS Avignon)

Cours C/C++

tvaira@free.fr

v0.1

7 / 69

Classes et objets

Destructeur
Le destructeur est la mthode membre appele lorsquune instance (objet) de classe cesse dexister en mmoire. Son rle est de librer toutes les ressources qui ont t acquises lors de la construction (typiquement librer la mmoire qui a t alloue dynamiquement par cet objet). Un destructeur est une mthode qui porte toujours le mme nom que la classe, prcd de "~". Il existe quelques contraintes :
Il ne possde aucun paramtre. Il ny en a quun et un seul. Il na jamais de type de retour.

Voil, on sait susamment de choses pour crire notre premire classe et instancier nos premiers objets.
tv (BTS IRIS Avignon) Cours C/C++ tvaira@free.fr v0.1 8 / 69

Classes et objets

Dclaration dune classe Point dans un chier point.h


// Une classe apporte un nouveau type : ici un Point. Cest donc un modle pour les futurs objets de type Point. // Mon type Point possde des caractristiques (des proprits) : une coordonne entire x et une coordonne entire y // Mon type point peut faire des choses (des oprations) : il est capable dafficher ses coordonnes class Point { private: int _x, _y; public: Point(int, int); // je suis le constructeur ~Point(); // je suis le destructeur int getX(); void setX(int); int getY(); void setY(int); void afficher(); };

tv (BTS IRIS Avignon)

Cours C/C++

tvaira@free.fr

v0.1

9 / 69

Classes et objets

Dnition des membres de la classe Point dans un chier point.cc


#include <iostream> // jutilise cout #include "point.h" // il me faut la dclaration de la classe Point using namespace std; // utile ! // je definis la mthode Point (donc le // pour que le compilateur comprenne et Point::Point(int x, int y) { cout << "Appel du constructeur Point _x = x; _y = y; } Point::~Point() { cout << "Appel du destructeur ~Point } int Point::getX() { return _x; } void Point::setX(int x) { _x = x; } int Point::getY() { return _y; } void Point::setY(int y) { _y = y; } void Point::afficher() { cout << _x << "," << _y << endl; } constructeur ici) de la classe Point la trouve, jutilise loprateur de rsolution de porte :: : jinitialise les membres privs x et y" << endl;

: jai rien faire" << endl;

tv (BTS IRIS Avignon)

Cours C/C++

tvaira@free.fr

v0.1

10 / 69

Classes et objets

Un programme dessai dans un chier main.cc


#include <iostream> // jutilise cout #include "point.h" // il me faut la dclaration de la classe Point using namespace std; // utile ! int main() { Point pointA(0,0); // jinstancie un objet pointA de type Point Point pointB(1,2); // ou je cre une instance pointB de type Point pointA.afficher(); // jappelle la mthode publique afficher() de lobjet pointA pointB.afficher(); // chaque objet possde ses propres attributs //pointB._y = 1; // interdit car lattribut _y est priv donc : pointB.setY(1); // je modifie la valeur de lattribut _y de pointB pointB.afficher(); return 0; }

tv (BTS IRIS Avignon)

Cours C/C++

tvaira@free.fr

v0.1

11 / 69

Classes et objets

Fabrication de lexcutable a.out (sous Linux)


$ g++ -c point.cc $ g++ -c main.cc $ ls *.o main.o point.o $ g++ main.o point.o # ou en une seule ligne : $ g++ main.cc point.cc

Excution du programme dessai


Appel Appel 0,0 1,2 1,1 Appel Appel du constructeur Point : jinitialise les membres privs x et y du constructeur Point : jinitialise les membres privs x et y

du destructeur ~Point : jai rien faire du destructeur ~Point : jai rien faire
Cours C/C++ tvaira@free.fr v0.1 12 / 69

tv (BTS IRIS Avignon)

Classes et objets

new et delete

Pour allouer dynamiquement en C++, on utilisera loprateur new. Celui-ci renvoyant une adresse o est cre la variable en question, il nous faudra un pointeur pour la conserver. Manipuler ce pointeur, reviendra manipuler la variable alloue dynamiquement. Pour librer de la mmoire alloue dynamiquement en C++, on utilisera loprateur delete.

tv (BTS IRIS Avignon)

Cours C/C++

tvaira@free.fr

v0.1

13 / 69

Classes et objets

Pour allouer dynamiquement un objet, on utilisera loprateur new. Exemple : allocation dynamique dun objet
#include <iostream> #include "point.h" using namespace std; int main() { Point *pointC; // je suis pointeur sur un objet de type Point pointC = new Point(2,2); // jalloue dynamiquement un objet de type Point pointC->afficher(); // Comme pointC est une adresse, je dois utiliser loprateur -> pour accder aux membres de cet objet pointC->setY(0); // je modifie la valeur de lattribut _y de pointB (*pointC).afficher(); // cette criture est possible : je pointe lobjet puis jappelle sa mthode afficher() delete pointC; // ne pas oublier de librer la mmoire alloue pour cet objet return 0; }

tv (BTS IRIS Avignon)

Cours C/C++

tvaira@free.fr

v0.1

14 / 69

Classes et objets

Cas particuliers

Un programme dessai qui pose problme !


#include <iostream> #include "point.h" using namespace std; int main() { Point pointA;

// dclaration dun objet pointD sans coordonnes (que faut-il faire ?)

tableauDe10Points[10]; // dclaration dun tableauDe10Points contenant 10 objets de type Point Point pointE(); return 0; } // que fait cette ligne ?

tv (BTS IRIS Avignon)

Cours C/C++

tvaira@free.fr

v0.1

15 / 69

Classes et objets

Rappel : paramtres par dfaut


Le langage C++ ore la possibilit davoir des valeurs par dfaut pour les paramtres dune fonction (ou dune mthode), qui peuvent alors tre sous-entendus au moment de lappel.

int mult(int a=2, int b=3) { return a*b; } mult(3,4); // donne 12 mult(3); // quivaut mult(3,3) qui donne 9 mult(); // quivaut mult(2,3) qui donne 6

Remarque : cette possibilit, permet dcrire quun seul constructeur protant du mcanisme de valeur par dfaut.
tv (BTS IRIS Avignon) Cours C/C++ tvaira@free.fr v0.1 16 / 69

Classes et objets

Constructeur par dfaut (1/4)

Deux constructeurs sont toujours ncessaires dans toute nouvelle classe : le constructeur par dfaut et le constructeur de copie. Ils sont tellement importants que si vous ne les crivez pas, le compilateur tentera de le faire votre place ... mais moins de savoir exactement ce que vous faites il vaut mieux les crire soi-mme. Le rle du constructeur par dfaut est de crer une instance non initialise quand aucun autre constructeur fourni nest applicable. Par exemple, le constructeur par dfaut de notre classe Point sera :
Point::Point() {} // Sans aucun paramtre !

tv (BTS IRIS Avignon)

Cours C/C++

tvaira@free.fr

v0.1

17 / 69

Classes et objets

Constructeur par dfaut (2/4)


Si on essaye de compiler les dclarations suivantes :
Point pointD; // un pointD sans coordonnes (que faut-il faire ?) Point tableauDe10Points[10]; // typiquement : les cases dun tableau de Point pointA.afficher(); tableauDe10Points[0].afficher(); // le premier objet Point du tableau

On obtient des erreurs en provenance du compilateur :


ligne 8: erreur: no matching function for call to Point::Point() ligne 9: erreur: no matching function for call to Point::Point()

tv (BTS IRIS Avignon)

Cours C/C++

tvaira@free.fr

v0.1

18 / 69

Classes et objets

Constructeur par dfaut (3/4)

Le compilateur na pas trouv de constructeur par dfaut dans notre classe, il faut donc le dclarer et le dnir. Dnition dun constructeur par dfaut sans argument :
Point::Point() { _x=0; _y=0; }

Maintenant, le programme prcdent se compile et le constructeur par dfaut sera appel pour lobjet pointA et 10 fois pour chaque objet Point du tableau.

tv (BTS IRIS Avignon)

Cours C/C++

tvaira@free.fr

v0.1

19 / 69

Classes et objets

Constructeur par dfaut (4/4)


Le constructeur par dfaut est donc un constructeur sans argument ou avec des arguments qui possdent une valeur par dfaut. Dclaration dun constructeur par dfaut avec arguments :
Point(int _x=0, int _y=0);

Dnition dun constructeur par dfaut avec arguments :


Point::Point(int _x/*=0*/, int _y/*=0*/) {}

Le constructeur par dfaut est ncessaire notamment dans : la cration de tableaux dobjet, la fabrication dobjets temporaires et lagrgation par valeur des objets.
tv (BTS IRIS Avignon) Cours C/C++ tvaira@free.fr v0.1 20 / 69

Classes et objets

Liste dinitialisation
Un meilleur moyen daecter des valeurs lors de la construction aux donnes membres de la classe est la liste dinitialisation. Dans le chier .cc, il sut dutiliser la syntaxe suivante :
Point::Point(int x, int y) : _x(x), _y(y) // cest la liste dinitialisation { /* il ny a rien dautre faire */ }

La liste dinitialisation permet dutiliser le constructeur de chaque donne membre, et ainsi dviter une aectation aprs coup. la liste dinitialisation doit tre utilise pour certains objets qui ne peuvent pas tre contruits par dfaut : cest le cas des rfrences et des objets constants. Important : lordre dinitialisation des membres doit correspondre celui de leurs dclarations dans le chier .h.
tv (BTS IRIS Avignon) Cours C/C++ tvaira@free.fr v0.1 21 / 69

Classes et objets

Le pointeur spcial dinstance : this

Dans certaines conditions particulires, il est ncessaire de disposer dun moyen de dsigner depuis lintrieur dune fonction membre, non pas les donnes membres, mais linstance elle-mme de la classe sur laquelle la mthode membre est appele. Le mot cl "this" permet de dsigner ladresse de linstance (de lobjet) sur laquelle la fonction membre a t appele.

tv (BTS IRIS Avignon)

Cours C/C++

tvaira@free.fr

v0.1

22 / 69

Classes et objets

Exemple dutilisation du pointeur spcial dinstance this

class A { public: // pour lexemple int x; A * getA(); void setX(int); }; void A::setX(int x) { this->x = x; } // Ici this permet de distinguer le paramtre x de lattribut x de lobjet de type A sur lequel on a appel setX A* A::getA() { return this; } // Ici this est ladresse de lobjet de type A sur lequel on a appel getA int main() { A a; A *pa; a.setX(2); pa = a.getA(); // quivalent (trs tordu !) pa = &a ! cout << "x=" << a.x << endl; // Affiche : x=2 cout << "x=" << pa->x << endl; // Affiche : x=2 return 0; }

tv (BTS IRIS Avignon)

Cours C/C++

tvaira@free.fr

v0.1

23 / 69

Classes et objets

Agrgation
Lagrgation signie implicitement contient un (ou est compose dun ou possde un ) ou tout simplement a un . On distingue deux types dagrgation : Agrgation interne : lobjet agrg est cr par lobjet agrgateur Agrgation externe : lobjet agrg a t cr extrieurement lobjet agrgateur Il y a 3 possibilits de mise en oeuvre : agrgation par valeur (appele aussi composition) agrgation par rfrence agrgation par pointeur Remarque : en rgle gnrale, le crateur dun objet est le responsable de sa destruction.
tv (BTS IRIS Avignon) Cours C/C++ tvaira@free.fr v0.1 24 / 69

Classes et objets

Agrgation interne par valeur (Composition)

class ObjetGraphique { public: ObjetGraphique(Point p, int couleur) : point(p), couleur(couleur) {} void afficher() { cout << point.getX() << "," << point.getY() << " [" << couleur << "]" << endl ; } private: Point point; // par valeur int couleur; }; Point p1(1, 1); ObjetGraphique o1(p1, 1); p1.setX(5); o1.afficher(); // donne : 1,1 [1]

tv (BTS IRIS Avignon)

Cours C/C++

tvaira@free.fr

v0.1

25 / 69

Classes et objets

Agrgation externe par rfrence

class ObjetGraphique { public: ObjetGraphique(Point &p, int couleur): point(p), couleur(couleur) {} void afficher() { cout << point.getX() << "," << point.getY() << " [" << couleur << "]" << endl ; } private: Point &point; // par rfrence int couleur; }; Point p1(2, 2); ObjetGraphique o1(p1, 1); p1.setX(5); o1.afficher(); // donne : 5,2 [1]

tv (BTS IRIS Avignon)

Cours C/C++

tvaira@free.fr

v0.1

26 / 69

Classes et objets

Agrgation externe par pointeur


class ObjetGraphique { public: ObjetGraphique(Point *p, int couleur) : point(p), couleur(couleur) {} ObjetGraphique(Point &p, int couleur) : point(&p), couleur(couleur) {} void afficher() { cout << point->getX() << "," << point->getY() << " [" << couleur << "]" << endl ; } private: Point *point; // par pointeur int couleur; }; Point p1(3, 3); Point p2(4, 4); ObjetGraphique o1(&p1, 1); ObjetGraphique o2(p2, 1); p1.setX(5); p2.setX(6); o1.afficher(); // donne : 5,3 [1] o2.afficher(); // donne : 6,4 [1]
tv (BTS IRIS Avignon) Cours C/C++ tvaira@free.fr v0.1 27 / 69

Classes et objets

Constructeur de copie (1/5)


Le constructeur de copie est appel dans : la cration dun objet partir dun autre objet pris comme modle le passage en paramtre dun objet par valeur une fonction ou une mthode le retour dune fonction ou une mthode renvoyant un objet La forme habituelle dun constructeur de copie est la suivante :
T(const T&);

Remarque : toute autre duplication (au cours de la vie dun objet) sera faite par loprateur daectation (=).

tv (BTS IRIS Avignon)

Cours C/C++

tvaira@free.fr

v0.1

28 / 69

Classes et objets

Constructeur de copie (2/5)

La forme habituelle dun constructeur de copie est la suivante :


T(const T&);

Lobjet modle est pass : en rfrence, ce qui assure de bonnes performances et empche un bouclage inni et la rfrence est constante, ce qui garantit que seules des mthodes constantes (ne pouvant pas modier les attributs) seront appelables sur lobjet pass en argument

tv (BTS IRIS Avignon)

Cours C/C++

tvaira@free.fr

v0.1

29 / 69

Classes et objets

Constructeur de copie (3/5)


On aura besoin de dnir son constructeur de copie : Agrgation par valeur : il faut recopier les objets agrgs par valeur en appelant leur constructeur par copie Agrgation par rfrence (ou pointeur) et allocation dynamique de mmoire : la copie optimise ne gnrant que des copies de pointeurs, les dirents objets utiliseraient les mme blocs mmoire. Exemple dun constructeur de copie basique :
T::T(const T& t):a(t.a) { }

Remarque : le compilateur fournit un constructeur de copie automatique par recopie bit bit optimise .
tv (BTS IRIS Avignon) Cours C/C++ v0.1 30 / 69

tvaira@free.fr

Classes et objets

Constructeur de copie (4/5)

Exemple : dclaration dune classe Ensemble


class Ensemble { private: enum { capacite_defaut = 100 }; int * t; int n; int capacite; public: Ensemble(int capacite=capacite_defaut); ~Ensemble(); Ensemble(const Ensemble &e); };

tv (BTS IRIS Avignon)

Cours C/C++

tvaira@free.fr

v0.1

31 / 69

Classes et objets

Constructeur de copie (4/5)


Exemple : dnition de la classe Ensemble
Ensemble::Ensemble(int capacite/*=capacite_defaut*/):n(0),capacite(capacite) { t = new int[capacite]; for (int i = 0; i < capacite ; i++) t[i] = 0; } Ensemble::~Ensemble() { delete [] t; } Ensemble::Ensemble(const Ensemble &e):n(e.n),capacite(e.capacite) { this->t = new int[e.capacite]; for (int i = 0; i < e.capacite ; i++) this->t[i] = e.t[i]; }

tv (BTS IRIS Avignon)

Cours C/C++

tvaira@free.fr

v0.1

32 / 69

Classes et objets

Destructeur
On aura besoin de dnir son destructeur ds lors que la classe ralise de : lagrgation par pointeur lallocation dynamique de mmoire Exemple dun destructeur basique :
A::A() { t = new int[10]; // allocation dynamique point = new Point; // agrgation par pointeur avec allocation dynamique } A::~A() { delete [] t; // on libre delete point; // on libre }

tv (BTS IRIS Avignon)

Cours C/C++

tvaira@free.fr

v0.1

33 / 69

Classes et objets

Oprateur daectation (1/2)


Il est ncessaire de crer un oprateur de copie lorsque lon fait de : lagrgation lallocation dynamique de mmoire Remarque : Dans tous les autres cas, le compilateur cre un oprateur daectation par recopie bit bit optimise . La forme habituelle doprateur daectation est la suivante :
T& operator=(const T&);

Remarque : Cet oprateur renvoie une rfrence sur T an de pouvoir lutiliser avec dautres aectations.
tv (BTS IRIS Avignon) Cours C/C++ tvaira@free.fr v0.1 34 / 69

Classes et objets

Oprateur daectation (2/2)


Exemple : dnition de loprateur daectation de la classe Ensemble
Ensemble & Ensemble::operator = (const Ensemble &e) { if (this != &e) { delete [] t; // attention lobjet avait dj t construit n = e.n; capacite = e.capacite; t = new int[e.capacite]; for (int i = 0; i < e.capacite ; i++) t[i] = e.t[i]; } return *this; }

Rappel : loprateur daectation est associatif droite a=b=c est value comme a=(b=c). Ainsi, la valeur renvoye par une aectation doit tre son tour modiable.
tv (BTS IRIS Avignon) Cours C/C++ tvaira@free.fr v0.1 35 / 69

Classes et objets

Forme Canonique de Coplien

Une classe T est dite sous forme canonique (ou forme normale ou forme standard) si elle prsente les mthodes suivantes :
class T { public: T (); // Constructeur par dfaut T (const T&); // Constructeur de copie ~T (); // Destructeur ventuellement virtuel T &operator= (const T&); // Operateur daffectation };

tv (BTS IRIS Avignon)

Cours C/C++

tvaira@free.fr

v0.1

36 / 69

Les objets constants

Objets constants

Les rgles suivantes sappliquent aux objets constants : On dclare un objet constant avec le modicateur const On ne peut appliquer que des mthodes constantes sur un objet constant Un objet pass en paramtre sous forme de rfrence constante est considr comme constant Remarque : une mthode constante est tout simplement une mthode qui ne modie aucun des attributs de lobjet. Il est conseill de qualier const toute fonction qui peut ltre.

tv (BTS IRIS Avignon)

Cours C/C++

tvaira@free.fr

v0.1

37 / 69

Les objets constants

Mthodes constantes
La qualication const dune fonction membre fait partie de sa signature. Ainsi, on peut surcharger une fonction membre non constante par une fonction membre constante :
class Point { private: int x, y; public: int X() const { return x; } int Y() const { return y; } int& X() { return x; } int& Y() { return y; } void afficher() { cout << X() << "," << Y() << endl ; } }; Point p1(1, 0); p1.afficher(); // donne : 1,0 int r; r = p1.X(); p1.Y() = r; p1.afficher(); // donne : 1,1
tv (BTS IRIS Avignon) Cours C/C++ tvaira@free.fr v0.1 38 / 69

Les objets constants

Attributs constants
Une donne membre dune classe peut tre qualie const. Il est alors obligatoire de linitialiser lors de la construction dun objet, et sa valeur ne pourra par la suite plus tre modie.

class Point { private: const char lettre; int x, y; public: Point(char lettre, int x, int y):lettre(lettre), x(x), y(y) ... void afficher() { cout << lettre << ":" << X() << "," << Y() << endl ; } }; Point p1(A, 1, 0); p1.afficher(); // donne : A:1,0

tv (BTS IRIS Avignon)

Cours C/C++

tvaira@free.fr

v0.1

39 / 69

Surcharge des oprateurs

Surcharge des oprateurs (1/3)

La surcharge doprateur permet aux oprateurs du C++ davoir une signication spcique quand ils sont appliqus des types spciques. Parmi les nombreux exemples que lon pourrait citer : myString + yourString pourrait servir concatner deux objets string maDate++ pourrait servir incrmenter un objet Date a * b pourrait servir multiplier deux objets Nombre e[i] pourrait donner accs un lment contenu dans un objet Ensemble

tv (BTS IRIS Avignon)

Cours C/C++

tvaira@free.fr

v0.1

40 / 69

Surcharge des oprateurs

Surcharge des oprateurs (2/3)


Oprateurs du C++ ne pouvant tre surchargs : . : Slection dun membre .* : Appel dun pointeur de mthode membre :: : Slection de porte :? : Oprateur ternaire sizeof, typeid, static_cast, dynamic_cast, const_cast, reinterpret_cast Oprateurs C++ quil vaut mieux ne pas surcharger : , : valuation squentielle dexpressions ! : Non logique || && : Ou et Et logiques
tv (BTS IRIS Avignon) Cours C/C++ tvaira@free.fr v0.1 41 / 69

Surcharge des oprateurs

Surcharge des oprateurs (3/3)


Oprateurs C++ que lon surcharge habituellement : Aectation, aectation avec opration (=, +=, *=, etc.) : Mthode Oprateur fonction () : Mthode Oprateur indirection * : Mthode Oprateur crochets [] : Mthode Incrmentation ++, dcrmentation : Mthode Oprateur che et che appel -> et ->* : Mthode Oprateurs de dcalage << et >> : Mthode Oprateurs new et delete : Mthode Oprateurs de lecture et criture sur ux << et >> : Fonction Oprateurs dyadiques genre arithmtique (+,-,/ etc) : Fonction

tv (BTS IRIS Avignon)

Cours C/C++

tvaira@free.fr

v0.1

42 / 69

Surcharge des oprateurs

Surcharge des oprateurs internes


La premire technique pour surcharger les oprateurs consiste les considrer comme des mthodes normales de la classe sur laquelle ils sappliquent.
A Op B se traduit par A.operatorOp(B) type & operator+=(const type &); // Dans une classe T : T & T::operator+=(const T &b) { x += b.x; return *this; }

Remarque : Les oprateurs de comparaison sont trs simples surcharger. La seule chose essentielle retenir est quils renvoient une valeur boolenne.
tv (BTS IRIS Avignon) Cours C/C++ tvaira@free.fr v0.1 43 / 69

Surcharge des oprateurs

Surcharge des oprateurs externes (1/2)


La deuxime technique utilise la surcharge doprateurs externes. La dnition de loprateur ne se fait plus dans la classe qui lutilise, mais en dehors de celle-ci. Dans ce cas, tous les oprandes de loprateur devront tre passs en paramtres.

A Op B se traduit par operatorOp(A, B) // Dans une classe T : friend T operator+(const T &a, const T &b); // Et globalement : T operator+(const T &a, const T &b) { T result = a; return result += b; }

tv (BTS IRIS Avignon)

Cours C/C++

tvaira@free.fr

v0.1

44 / 69

Surcharge des oprateurs

Surcharge des oprateurs externes (2/2)

Lavantage de cette syntaxe est que loprateur est rellement symtrique, contrairement ce qui se passe pour les oprateurs dnis lintrieur de la classe. On constate que les oprateurs externes doivent tre dclars comme tant des fonctions amies (friend) de la classe sur laquelle ils travaillent, faute de quoi ils ne pourraient pas manipuler les donnes membres de leurs oprandes.

tv (BTS IRIS Avignon)

Cours C/C++

tvaira@free.fr

v0.1

45 / 69

Surcharge des oprateurs

Oprateurs dincrmentation et de dcrmentation (1/3)

Les oprateurs dincrmentation et de dcrmentation ont la mme notation mais reprsentent deux oprateurs en ralit. En eet, ils nont pas la mme signication, selon quils sont placs avant ou aprs leur oprande. Ne possdant pas de paramtres (ils ne travaillent que sur lobjet), il est donc impossible de les direncier par surcharge. La solution qui a t adopte est de les direncier en donnant un paramtre ctif de type int lun dentre eux.
oprateurs prxs : ++ et ne prennent pas de paramtre et doivent renvoyer une rfrence sur lobjet lui-mme oprateurs suxs : ++ et prennent un paramtre int ctif (que lon nutilisera pas) et peuvent se contenter de renvoyer la valeur de lobjet

tv (BTS IRIS Avignon)

Cours C/C++

tvaira@free.fr

v0.1

46 / 69

Surcharge des oprateurs

Oprateurs dincrmentation et de dcrmentation (2/3)


Sous forme de mthode :

// Oprateur prfixe : T &T::operator++(void) { ++x ; // incrmente la variable return *this ; // et la retourne } // Oprateur suffixe : retourne la valeur et incrmente la variable T T::operator++(int n) { // cre un objet temporaire, T tmp(x); // peut nuire gravement aux performances ++x; return tmp; }

tv (BTS IRIS Avignon)

Cours C/C++

tvaira@free.fr

v0.1

47 / 69

Surcharge des oprateurs

Oprateurs dincrmentation et de dcrmentation (3/3)


Sous forme de fonctions amies :

// Oprateur prfixe T operator++(T &a) { ++a.x; return a; } // Oprateur suffixe T operator++(T &a, int n) { T tmp = a; ++a.x; return tmp; }

tv (BTS IRIS Avignon)

Cours C/C++

tvaira@free.fr

v0.1

48 / 69

Lhritage

Lhritage (1/2)
Lhritage (ou spcialisation, ou drivation) permet dajouter des proprits une classe existante pour en obtenir une nouvelle plus prcise. Lide est : "un B est un A avec des choses en plus".

Exemple : Un tudiant est une personne, et a donc un nom et un prnom. De plus, il a un numro INE.
tv (BTS IRIS Avignon) Cours C/C++ tvaira@free.fr v0.1 49 / 69

Lhritage

Lhritage (2/2)
// A est la classe parente ou mre de B (en anglais superclass) class A { public: void f(); }; // B est la classe fille ou drive de A : B hrite ou descend de A class B : public A { public: void g(); }; A a; B b; a.f(); b.g(); b.f(); a.g(); // // // // legal : legal : legal : illegal a b b : est un A est un B est un A (par hritage) a na pas de membre g() car a nest pas un B

tv (BTS IRIS Avignon)

Cours C/C++

tvaira@free.fr

v0.1

50 / 69

Lhritage

Conversion automatique
Si B hrite de A, alors toutes les instances de B sont aussi des instances de A, et il est donc possible de faire :
A a; B b; a = b; // Proprit conserve lorsquon utilise des pointeurs : A *pa; B *pb=&b; pa = pb;//car pointer sur un B cest avant tout pointer sur un A // videment, linverse nest pas vrai : A a; B b; b = a; // ERREUR ! // Pareil pour les pointeurs : A *pa=&a; B *pb; pb=pa;//ERREUR : car pointer sur un A nest pas pointer sur un B

Conclusion : Traiter un type driv comme sil tait son type de base est appel transtypage ascendant ou surtypage (upcasting ). A loppos, les transtypage descendant (downcast ) posent un problme particulier car leur vrication nest possible qu lexcution. Ils ncessitent lutilisation doprateur de cast : dynamic_cast (vu plus tard).
tv (BTS IRIS Avignon) Cours C/C++ tvaira@free.fr v0.1 51 / 69

Les exceptions

Gestion des exceptions (1/2)


Les exceptions ont t rajoutes la norme du C++ an de faciliter la mise en oeuvre de code robuste.

Dcoupage du traitement derreur en deux parties : le dclenchement : instruction throw le traitement : deux instructions insparables try et catch

tv (BTS IRIS Avignon)

Cours C/C++

tvaira@free.fr

v0.1

52 / 69

Les exceptions

Gestion des exceptions (2/2)


Une exception est leve ... Si linstruction en faute nest pas dans un bloc try, il y appel immdiat de la fonction terminate. Si linstruction en faute est incluse dans un bloc try, le programme saute directement vers les gestionnaires dexception quil examine squentiellement dans lordre du code source :
Si lun des gestionnaires correspond au type de lexception, il est excut, et, sil ne provoque pas lui mme dinterruption ou ne met n lexcution du programme, lexcution se poursuit la premire ligne de code suivant lensemble des gestionnaires dinterruption. En aucun cas il nest possible de poursuivre lexcution la suite de la ligne de code fautive. Si aucun gestionnaire ne correspond au type de lexception, celle-ci est propage au niveau suprieur de traitement des exceptions (cas de blocs try imbriqus) jusqu arriver au programme principal qui lui appellera terminate.
tv (BTS IRIS Avignon) Cours C/C++ tvaira@free.fr v0.1 53 / 69

Les exceptions

(Re)lancer une exception


Exemple :
#include <stdexcept> // pour std::range_error double inverse(double x) { if(x == 0.0) // lance une exception throw range_error("Division par zero !\n") ; else return 1/x; } try { inverse(0.0); } catch (range_error &e) { // traitement local throw; // relance lexception }

tv (BTS IRIS Avignon)

Cours C/C++

tvaira@free.fr

v0.1

54 / 69

Les exceptions

Dclarer ses exceptions (1/2)


Selon la norme, les exceptions peuvent tre de nimporte quel type (y compris un simple entier). Toutefois, il est utile de les dnir en tant que classes. Pour cela, on drive la classe fournit en standard std::exception et on surchargera au minimum la mthode what(). Exemple :
class ErreurX: public exception { public: ErreurX() throw() {} ~ErreurX() throw() {} const char *what(void) const throw() { // on peut aussi utiliser un string en priv return "Exception sur ..."; } };

tv (BTS IRIS Avignon)

Cours C/C++

tvaira@free.fr

v0.1

55 / 69

Les exceptions

Dclarer ses exceptions (2/2)


Exemple :
try { // bloc de code protg } catch (ErreurX &e) { cerr << "Erreur : " << e.what() << endl; } catch (exception &e) { cerr << "Exception inconnue : " << e.what() << endl; cerr << "Fin du programme" << endl ; // ou pas exit(1); }

tv (BTS IRIS Avignon)

Cours C/C++

tvaira@free.fr

v0.1

56 / 69

Les exceptions

Les spcicateurs dexception


Un spcicateur dexception renseigne lutilisateur sur le type des exceptions que peut renvoyer une mthode.
class A { private: int x; public: A(int x = 0) throw (ErreurX); };

Mais, le spcicateur dexception interdit aux autres mthodes (ou fonctions) appeles dinvoquer des exceptions non prvues. Hors, ce point est dicile vrier lors de la compilation. Aussi, les spcicateurs dexception doivent ils tre rservs au code matris totalement et plus spciquement aux mthodes pour lesquelles on est en mesure de prvoir le droulement complet.
tv (BTS IRIS Avignon) Cours C/C++ tvaira@free.fr v0.1 57 / 69

Polymorphisme

Comportement Polymorphe (1/4)


Par exemple, dans le diagramme suivant, lobjet Contrleur doiseaux travaille seulement avec des objets Oiseaux gnriques, et ne sait pas de quel type ils sont. Cest pratique du point de vue de Contrleur doiseaux, car il na pas besoin dcrire du code spcique pour dterminer le type exact dOiseau avec lequel il travaille, ou le comportement de cet Oiseau.

tv (BTS IRIS Avignon)

Cours C/C++

tvaira@free.fr

v0.1

58 / 69

Polymorphisme

Comportement Polymorphe (2/4)


Comment se fait-il donc que, lorsque bouger() est appel tout en ignorant le type spcique de lOiseau, on obtienne le bon comportement (une Oie court, vole ou nage, et un Pingouin court ou nage) ? La rponse constitue lastuce fondamentale de la programmation oriente objet : le compilateur ne peut faire un appel de fonction au sens traditionnel du terme. Un appel de fonction gnr par un compilateur non orient objet cre ce quon appelle une association prdnie : le compilateur gnre un appel un nom de fonction spcique, et lditeur de liens rsout cet appel ladresse absolue du code excuter. En POO, le programme ne peut dterminer ladresse du code avant la phase dexcution, un autre mcanisme est donc ncessaire quand un message est envoy un objet gnrique.
tv (BTS IRIS Avignon) Cours C/C++ tvaira@free.fr v0.1 59 / 69

Polymorphisme

Comportement Polymorphe (3/4)


Pour rsoudre ce problme, les langages orients objet utilisent le concept dassociation tardive. Quand un objet reoit un message, le code appel nest pas dtermin avant lexcution. Le compilateur sassure que la fonction existe et vrie le type des arguments et de la valeur de retour, mais il ne sait pas exactement quel est le code excuter. Pour crer une association tardive, le compilateur C++ insre une portion spciale de code en lieu et place de lappel absolu. Ce code calcule ladresse du corps de la fonction, en utilisant des informations stockes dans lobjet. Ainsi, chaque objet peut se comporter diremment suivant le contenu de cette portion spciale de code. Quand un objet reoit un message, lobjet sait quoi faire de ce message.

tv (BTS IRIS Avignon)

Cours C/C++

tvaira@free.fr

v0.1

60 / 69

Polymorphisme

Comportement Polymorphe (4/4)

On dclare quon veut une fonction qui ait la exibilit des proprits de lassociation tardive en utilisant le mot-cl virtual. On na pas besoin de comprendre les mcanismes de virtual pour lutiliser, mais sans lui on ne peut pas faire de la programmation oriente objet en C++. En C++, on doit se souvenir dajouter le mot-cl virtual (devant une mthode) parce que, par dfaut, les fonctions membres ne sont pas lies dynamiquement. Les fonctions virtuelles permettent dexprimer des dirences de comportement entre des classes de la mme famille. Ces dirences sont ce qui engendre un comportement polymorphe.

tv (BTS IRIS Avignon)

Cours C/C++

tvaira@free.fr

v0.1

61 / 69

Polymorphisme

Exemple : comportement non polymorphe (1/2)


#include <iostream> using namespace std; class Forme { public: Forme() { cout << "constructeur Forme <|- "; } void dessiner() { cout << "je dessine ... une forme ?\n"; } }; class Cercle : public Forme { public: Cercle() { cout << "Cercle\n"; } void dessiner() { cout << "je dessine un Cercle !\n"; } }; class Triangle : public Forme { public: Triangle() { cout << "Triangle\n"; } void dessiner() { cout << "je dessine un Triangle !\n"; } };

tv (BTS IRIS Avignon)

Cours C/C++

tvaira@free.fr

v0.1

62 / 69

Polymorphisme

Exemple : comportement non polymorphe (2/2)


void faireQuelqueChose(Forme &f) { f.dessiner(); // dessine une Forme } int main() { Cercle c; Triangle t; faireQuelqueChose(c); // avec un cercle faireQuelqueChose(t); // avec un triangle return 0; }

tv (BTS IRIS Avignon)

Cours C/C++

tvaira@free.fr

v0.1

63 / 69

Polymorphisme

Lexcution du programme dessai nous montre que nous nobtenons pas un comportement polymorphe puisque cest la mthode dessiner() de la classe Forme qui est appele :
constructeur Forme constructeur Forme je dessine ... une je dessine ... une <|- Cercle <|- Triangle forme ? forme ?

tv (BTS IRIS Avignon)

Cours C/C++

tvaira@free.fr

v0.1

64 / 69

Polymorphisme

Exemple : comportement polymorphe (1/2)


#include <iostream> using namespace std; class Forme { public: Forme() { cout << "constructeur Forme <- "; } // la mthode dessiner sera virtuelle et fournira un comportement polymorphe virtual void dessiner() { cout << "je dessine ... une forme ?\n"; } }; class Cercle : public Forme { public: Cercle() { cout << "Cercle\n"; } void dessiner() { cout << "je dessine un Cercle !\n"; } }; class Triangle : public Forme { public: Triangle() { cout << "Triangle\n"; } void dessiner() { cout << "je dessine un Triangle !\n"; } };
tv (BTS IRIS Avignon) Cours C/C++ v0.1 65 / 69

tvaira@free.fr

Polymorphisme

Exemple : comportement polymorphe (2/2)


void faireQuelqueChose(Forme &f) { f.dessiner(); // dessine une Forme } int main() { Cercle c; Triangle t; faireQuelqueChose(c); // avec un cercle faireQuelqueChose(t); // avec un triangle return 0; }

tv (BTS IRIS Avignon)

Cours C/C++

tvaira@free.fr

v0.1

66 / 69

Polymorphisme

Lexcution du programme dessai nous montre maintenant que nous obtenons un comportement polymorphe puisque cest la bonne mthode dessiner() qui est appele :
constructeur Forme <|- Cercle constructeur Forme <|- Triangle je dessine un Cercle ! je dessine un Triangle !

tv (BTS IRIS Avignon)

Cours C/C++

tvaira@free.fr

v0.1

67 / 69

Transtypage

Le transtypage en C++

Le transtypage (cast ou conversion de type) en C++ permet la conversion dun type vers un autre. Nouvelle syntaxe de loprateur traditionnel :
En C : (nouveau type)(expression transtyper) ; En C++ : type(expression transtyper) ;

Deux situations en cas dhritage :


transtypage ascendant (upcast ) : changer un type vers son type de base transtypage descendant (downcast ) : conversion dun pointeur sur un objet dune classe gnrale vers un objet dune classe spcialise.

tv (BTS IRIS Avignon)

Cours C/C++

tvaira@free.fr

v0.1

68 / 69

Transtypage

Traiter un type driv comme sil tait son type de base est appel transtypage ascendant, surtypage ou gnralisation (upcasting ). Cela ne pose donc aucun problme. Exemple : transtypage ascendant
class Forme {}; class Cercle : public Forme {}; class Triangle : public Forme {} ; void faireQuelqueChose(Forme &f) { f.dessiner(); } ... Cercle c; // Un Cercle est ici pass une fonction qui attend une Forme. // Comme un Cercle est une Forme, il peut tre trait comme tel par faireQuelqueChose() faireQuelqueChose(c);

tv (BTS IRIS Avignon)

Cours C/C++

tvaira@free.fr

v0.1

69 / 69