Sie sind auf Seite 1von 11

TP POO C++ n1

2013 tv <tvaira@free.fr> - v.1.0

Sommaire
Rappels Travail demand Notion de pile . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . La classe PileChar . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Paramtre par dfaut . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Liste dinitialisation . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Destructeur . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Les services rendus . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Constructeur de copie . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Oprateur daectation . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Surcharge doprateurs . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Intrt et utilisation dune pile . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2 2 2 3 3 4 4 5 5 6 7 11

Les objectifs de ce tp sont de dcouvrir la programmation oriente objet en C++.

TRAVAIL DEMAND

Rappels
La programmation oriente objet consiste dnir des objets logiciels et les faire interagir entre eux. Concrtement, un objet est une structure de donnes (ses attributs c.--d. des variables) qui dnit son tat et une interface (ses mthodes c.--d. des fonctions) qui dnit son comportement. Une classe dclare des proprits communes un ensemble dobjets. Un objet est cr partir dun modle appel classe. Chaque objet cr partir de cette classe est une instance de la classe en question.

Travail demand
Nous allons successivement dcouvrir les notions suivantes : lutilisation de paramtres par dfaut et de liste dinitialisation lcriture dun destructeur limplmentation dun constructeur de copie et de loprateur daectation la surcharge doprateurs On vous fournit un programme testPileChar.cpp o vous devez dcommenter progressivement les parties de code source correspondant aux questions poses.

Notion de pile
Une pile ( stack en anglais) est une structure de donnes base sur le principe Dernier arriv, premier sorti , ou LIFO (Last In, First Out ), ce qui veut dire que les derniers lments ajouts la pile seront les premiers tre rcuprs.

Le fonctionnement est celui d'une pile d'assiettes : on ajoute des assiettes sur la pile, et on les rcupre dans l'ordre inverse, en commenant par la dernire ajoute.
Une pile est utilise en gnral pour grer un historique de donnes (pages webs visites, ...) ou dactions (les fonctions Annuler de beaucoup de logiciels par exemple). La pile est utilise aussi pour tous les paramtres dappels et les variables locales des fonctions dans les langages compils. Voici quelques fonctions communment utilises pour manipuler des piles : Empiler : ajoute ou dpose un lment sur la pile Dpiler : enlve un lment de la pile et le renvoie La pile est-elle vide ? : renvoie vrai si la pile est vide, faux sinon La pile est-elle pleine ? : renvoie vrai si la pile est pleine, faux sinon Nombre dlments dans la pile : renvoie le nombre dlments prsents dans la pile Taille de la pile : renvoie le nombre maximum dlments pouvant tre dposs dans la pile Quel est llment de tte ? : renvoie llment de tte (le sommet) sans le dpiler

TP POO C++ n1

2 / 11

2013 tv <tvaira@free.fr>

TRAVAIL DEMAND

La classe PileChar
Le but est de raliser une structure de pile pouvant traiter des caractres (type char). La classe PileChar contient trois donnes membres prives : deux entiers strictement positifs, nomms max et sommet, et un pointeur sur un caractre, nomm pile. La donne membre max contient la taille de la pile cre pour cette instance de la classe, autrement dit le nombre maximum de caractres quil sera possible dy mettre. La donne membre sommet indique le numro de la case dans laquelle on pourra empiler le prochain caractre. Ce nest donc pas exactement le sommet de la pile, mais un cran au dessus. Le pointeur sur un caractre pile dsigne le tableau de caractres, allou dynamiquement (avec new) pour mmoriser le contenu de la pile. Dans cet exemple, on a successivement empil les quatre lettres du mot "pile". Ici, max vaut 5 (le nombre maximal de lettre empilable). et sommet vaut 4 puisque le dernier lment empil est le e du mot "pile", et que le prochain empilage se fera en pile[4].

Paramtre par dfaut


Il y a videment un constructeur qui prend en paramtre un entier strictement positif pour prciser la taille dsire pour la pile, future valeur pour max. On prcisera pour ce paramtre, une valeur par dfaut de 50 (cest une constante !). 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. Cette possibilit, permet dcrire quun seul constructeur protant du mcanisme de valeur par dfaut :
#define TAILLE_PAR_DEFAUT 50 // Active les affichages de debuggage pour les constructeurs et destructeur #define DEBUG class PileChar { private: unsigned int max; unsigned int sommet; char *pile; public: PileChar(int taille=TAILLE_PAR_DEFAUT); // je suis le constructeur (par dfaut) de la classe PileChar }; PileChar.h

TP POO C++ n1

3 / 11

2013 tv <tvaira@free.fr>

TRAVAIL DEMAND

Liste dinitialisation
Un meilleur moyen daecter des valeurs aux donnes membres de la classe lors de la construction est la liste dinitialisation. On va utiliser cette technique pour dnir le constructeur de la classe PileChar :
PileChar::PileChar(int taille/*=TAILLE_PAR_DEFAUT*/) : max(taille), sommet(0) // cest la liste dinitialisation { pile = new char[max]; // allocation dynamique du tableau de caractre #ifdef DEBUG cout << "PileChar(" << taille << ") : " << this << "\n"; #endif } PileChar.cpp

La liste d'initialisation permet d'utiliser le constructeur de chaque donne membre, et ainsi d'viter une aectation aprs coup. La liste d'initialisation doit tre utilise pour certains objets qui ne peuvent pas tre contruits par dfaut : c'est le cas des rfrences et des objets constants.

Destructeur
Le destructeur est la mthode membre appele automatiquement 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. La forme habituelle dun destructeur est la suivante :
class T { public: ~T(); // destructeur };

Pour viter les fuites de mmoire, le destructeur de la classe PileChar doit librer la mmoire alloue au tableau de caractres pile : On le dnit de la manire suivante :
PileChar::~PileChar() { delete [] pile; #ifdef DEBUG cout << "~PileChar() : " << this << "\n"; #endif } PileChar.cpp

TP POO C++ n1

4 / 11

2013 tv <tvaira@free.fr>

TRAVAIL DEMAND Question 1. Complter les chiers PileChar.cpp et PileChar.h fournis an dimplmenter le constructeur et le destructeur de cette classe. Dcommenter les parties de code de cette question dans le chier testPileChar.cpp et tester. Vrier quil y a bien autant dachages de destructeurs que de constructeurs.
PileChar pile1a; // construit une pile avec une taille par dfaut PileChar pile1b(10); // construit une pile avec une taille de 10 caractres

Les services rendus


Direntes mthodes publiques doivent tre dclares et dnies dans la classe : Une mthode taille() qui donne comme rsultat un entier positif qui est le nombre maximum de caractres quil sera possible dy mettre Une mthode compter() qui donne comme rsultat un entier positif qui est le nombre dlments actuellement prsents sur la pile Une mthode afficher() qui ache entre des [ et ] les lments actuellement prsents dans la pile. Sur lexemple prcdant, cette mthode donnerait lachage suivant : "[pile]" Une mthode empiler() qui prend un caractre en paramtre et le place sur le dessus de la pile Une mthode depiler() qui enlve le caractre du dessus de la pile et le renvoi en valeur de retour

Pour les mthodes empiler() et depiler(), on prendra garde vrier que l'opration demande est bien possible (attention aux piles pleines et aux piles vides). On achera un message d'erreur sur cerr dans les cas o l'opration ne peut tre eectue.
Question 2. Complter les chiers PileChar.cpp et PileChar.h fournis an dimplmenter ces services. Dcommenter les parties de code de cette question dans le chier testPileChar.cpp et tester. Vrier que vous obtenez les rsultats ci-dessous.
Pile vide ! Pile pleine ! Pile pleine ! Contenu de pile2 : [hello] Nombre dlments prsents sur pile2 : 5 Taille de pile2 : 5 Contenu de pile2 : [hell] Nombre dlments prsents sur pile2 : 4

Constructeur de copie
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

Remarque : toute autre duplication (au cours de la vie d'un objet) sera faite par l'oprateur d'aectation (=).

TP POO C++ n1

5 / 11

2013 tv <tvaira@free.fr>

TRAVAIL DEMAND La forme habituelle dun constructeur de copie est la suivante :


class T { public: T(const T&); };

Donc pour la classe PileChar :


PileChar::PileChar(const PileChar &p) : max(p.max), sommet(p.sommet) { pile = new char[max]; // on alloue dynamiquement le tableau de caractre unsigned int i; // on recopie les lments de la pile for (i = 0; i < sommet ; i++) pile[i] = p.pile[i]; #ifdef DEBUG cout << "PileChar(const PileChar &p) : " << this << "\n"; #endif }

Deux situations o le constructeur de copie est ncessaire :


PileChar pile3a(pile2); // Appel du constructeur de copie pour instancier pile3a PileChar pile3b = pile1b; // Appel du constructeur de copie pour instancier pile3b

Question 3. Complter les chiers PileChar.cpp et PileChar.h fournis an dimplmenter le constructeur de copie. Dcommenter les parties de code de cette question dans le chier testPileChar.cpp et tester. Vrier que vous obtenez les rsultats ci-dessous et quil y a bien autant dachages de destructeurs que de constructeurs.
Contenu de pile3a : [hell] Nombre dlments prsents sur pile3a : 4 Taille de pile3a : 5 Contenu de pile3b : [] Nombre dlments prsents sur pile3b : 0 Taille de pile3b : 10

Oprateur daectation
Loprateur daectation (=) est un oprateur de copie dun objet vers un autre. Lobjet aect est dj cr sinon cest le constructeur de copie qui sera appel. La forme habituelle doprateur daectation est la suivante :
class T { public: T& operator=(const T&); };

TP POO C++ n1

6 / 11

2013 tv <tvaira@free.fr>

TRAVAIL DEMAND

Cet oprateur renvoie une rfrence sur T an de pouvoir l'utiliser avec d'autres aectations. En eet, l'oprateur d'aectation est associatif droite a=b=c est value comme a=(b=c). Ainsi, la valeur renvoye par une aectation doit tre son tour modiable.
La dnition de loprateur = est la suivante :
PileChar& PileChar::operator = (const PileChar &p) { // vrifions si on ne sauto-copie pas ! if (this != &p) { delete [] pile; // on libre lancienne pile max = p.max; sommet = p.sommet; pile = new char[max]; // on alloue une nouvelle pile unsigned int i; for (i = 0; i < sommet ; i++) pile[i] = p.pile[i]; // on recopie les lments de la pile } #ifdef DEBUG cout << "operator= (const PileChar &p) : " << this << "\n"; #endif return *this; }

Ce qui permettra dcrire :


PileChar pile4; // Appel du constructeur par dfaut pour crer pile4 pile4 = pile3a; // Appel de loprateur daffectation pour copier pile3a dans pile4

Question 4. Complter les chiers PileChar.cpp et PileChar.h fournis an dimplmenter loprateur daectation =. Dcommenter les parties de code de cette question dans le chier testPileChar.cpp et tester. Vrier que vous obtenez les rsultats ci-dessous. Expliquer pourquoi le message derreur "Pile pleine !" sache ?
Taille de pile4 : 50 Pile pleine ! Pile pleine ! Contenu de pile4 : [hello] Nombre dlments prsents sur pile4 : 5 Taille de pile4 : 5

Surcharge doprateurs
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

TP POO C++ n1

7 / 11

2013 tv <tvaira@free.fr>

TRAVAIL DEMAND Les 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

Les autres oprateurs ne peuvent pas soit tre surchargs soit il est dconseill de le faire.
La premire technique pour surcharger les oprateurs consiste les considrer comme des mthodes normales de la classe sur laquelle ils sappliquent. Le principe est le suivant :
A Op B se traduit par A.operatorOp(B) t1 == t2; // quivalent : t1.operator==(t2) t1 += t2; // quivalent : t1.operator+=(t2)

On surcharge les oprateurs ==, != et += pour la classe PileChar :


class PileChar { private: unsigned int max; unsigned int sommet; char *pile; public: ... bool operator == (const PileChar &p); // teste si deux piles sont identiques bool operator != (const PileChar &p); // teste si deux piles sont diffrentes PileChar& operator += (const PileChar &p); // empile une pile sur une autre }; bool PileChar::operator == (const PileChar &p) { if(max != p.max) return false; if(sommet != p.sommet) return false; unsigned int i; for (i = 0; i < sommet ; i++) if(pile[i] != p.pile[i]) return false; return true; } bool PileChar::operator != (const PileChar &p) { // TODO }

TP POO C++ n1

8 / 11

2013 tv <tvaira@free.fr>

TRAVAIL DEMAND
PileChar& PileChar::operator += (const PileChar &p) { unsigned int i, j; // Reste-il assez de place pour empiler les caractres ? if((sommet + p.sommet) <= max) { for (i = sommet, j = 0; j < p.sommet ; i++, j++) pile[i] = p.pile[j]; // on recopie les lments de la pile sommet += j; // on met jour le nouveau sommet } else cerr << "Pile pleine !\n"; return *this; }

Question 5. Complter les chiers PileChar.cpp et PileChar.h fournis an dimplmenter les oprateurs ==, != et +=. Dcommenter les parties de code de cette question dans le chier testPileChar.cpp et tester. Vrier que vous obtenez les rsultats ci-dessous.
pile3a et pile2 identiques ! pile3a et pile4 diffrentes ! Taille de pile5 : 6 Contenu de pile5 : [hello] Nombre dlments prsents sur pile5 : 5 Taille de pile5 : 6 Pile pleine ! Contenu de pile5 : [hello]

On dsire aussi surcharger loprateur += pour empiler une simple caractre. De la mme manire, on va surcharger loprateur -= pour supprimer n caractres depuis le haut de la pile :
PileChar pile6; pile6 pile6 pile6 ... pile6 += a; // empile le caractre a += z; // empile le caractre z += e; // empile le caractre e -= 2; // supprime 2 caractres du haut de la pile (donc e puis z)

Question 6. Complter les chiers PileChar.cpp et PileChar.h fournis an de surcharger les oprateurs += et -=. Dcommenter les parties de code de cette question dans le chier testPileChar.cpp et tester. Vrier que vous obtenez les rsultats ci-dessous.
Contenu de pile6 : [azerty] Nombre dlments prsents sur pile6 : 6 Taille de pile6 : 50 Donner le nombre de caractres supprimer dans pile6 : 2 Contenu de pile6 : [azer] Nombre dlments prsents sur pile6 : 4

TP POO C++ n1

9 / 11

2013 tv <tvaira@free.fr>

TRAVAIL DEMAND La deuxime technique utilise la surcharge doprateurs externes sous forme de fonctions. 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. Le principe est le suivant :
A Op B se traduit par operatorOp(A, B) t1 + t2; // quivalent : operator+(t1, t2)

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.
Exemple pour une classe T :
class T { private: int x; public: friend T operator+(const T &a, const T &b); }; T operator+(const T &a, const T &b) { // solution n 1 : T result = a; result.x += b.x; return result; // solution n 2 : si loprateur += a t surcharg T result = a; return result += b; } T t1, t2, t3; // Des objets de type T t3 = t1 + t2; // Appel de loprateur + puis de loprateur de copie (=) t3 = t2 + t1; // idem car loprateur est symtrique

L'avantage de cette syntaxe est que l'oprateur est rellement symtrique, contrairement ce qui se passe pour les oprateurs dnis l'intrieur de la classe.
Question 7. Complter les chiers PileChar.cpp et PileChar.h fournis an de surcharger loprateur + sour forme de fonction amie externe. Dcommenter les parties de code de cette question dans le chier testPileChar.cpp et tester. Vrier que vous obtenez les rsultats ci-dessous. Proter pour bien reprer les instants du droulement du programme o ont lieu les appels aux constructeurs, destructeurs et aectations, ventuellement en plaant des achages supplmentaires dans votre programme.

TP POO C++ n1

10 / 11

2013 tv <tvaira@free.fr>

TRAVAIL DEMAND
Contenu de pile7 : [azerhello] Nombre dlments prsents sur pile7 : 9 Taille de pile7 : 50

Intrt et utilisation dune pile


Par exemple, on peut trs simplement inverser les lments contenus dans un tableau ou dans une chane de caractres (pour tester un palindrome) en utilisant une pile. Il sut dempiler les lments sur une pile puis de reconstituer le tableau (ou la chane) inverse en dpilant les lments. Question 8. crire dans le chier testPileChar.cpp une fonction affiche_inverse() recevant en paramtre une pile et qui dpile les lettres qui y sont contenues en les crivant lcran au fur et mesure. ATTENTION : Cette fonction ne doit pas modier le contenu de la pile dclare dans le main() ... Comment sy prendre ?
Contenu de pile8 : [soleil] Contenu inverse de pile8 : lielos Contenu de pile8 : [soleil]

Pour nir, on dsire pouvoir crer des piles partir de chanes de caractres C (const char []) ou C++ (string). Pour cela, on va dclarer deux nouveaux constructeurs pour la classe PileChar :
class PileChar { private: unsigned int max; unsigned int sommet; char *pile; public: ... PileChar(const string &init); // pour les chanes de caractres en C++ PileChar(const char init[]); // pour les chanes de caractres en C ... };

Question 9. Complter les chiers PileChar.cpp et PileChar.h fournis an dimplmenter ces deux nouveaux constructeurs. Dcommenter les parties de code de cette question dans le chier testPileChar.cpp et tester. Vrier que vous obtenez les rsultats ci-dessous.
Contenu de pile9a : [Bonjour] Nombre dlments prsents sur pile9a : 7 Taille de pile9a : 7 Contenu inverse de pile9a : ruojnoB Contenu de pile9b : [Hello world] Nombre dlments prsents sur pile9b : 11 Taille de pile9b : 11 Contenu inverse de pile9b : dlrow olleH

TP POO C++ n1

11 / 11

2013 tv <tvaira@free.fr>