Exercices Résolus de Programmation Orientée Objets
Exercices Résolus de Programmation Orientée Objets
Exercices Résolus de Programmation Orientée Objets
Exercice 1:
L'objet de cet exercice est d'utiliser une fonction amie qui est membre d'une autre classe
Soient les deux classes
Class matrice
{Float mat[3][3];
Public:
matrice (float t[3][3]);
vecteur prod(vecteur);
};
Class vecteur
{Float v[3];
Public:
vecteur (float t[3]);
friend vecteur matrice::prod(vecteur);
void affiche();
};
Ecrire une fonction main() qui permet de tester ces fonctions
Exercice 2:
1°) On souhaite manipuler des tableaux de réels. Pour cela, on implémentera une instance de
la classe Tableau comme un tableau dynamique de réels, comme suit :
Class Tableau
{
private :
in *tab ;
int taille;
public:
--------
};
Page n° :1/6
D’implémenter la méthode Tri qui permet de trier le tableau selon l’ordre croissant.
D’implémenter la méthode Palindrome qui vérifie si un tableau est palindrome ou pas.
D’implémenter l’opérateur +, permettant de réaliser la somme de deux tableaux de
même taille.
D’implémenter l’opérateur *, permettant de réaliser le produit scalaire de deux
tableaux de même taille.
D’implémenter l’opérateur *, permettant de réaliser le produit d’un tableau par un
scalaire.
D’implémenter l’opérateur * comme méthode amie , permettant de réaliser le produit
d’un scalaire par un tableau.
D’implémenter l’opérateur d’affectation
Surdéfinir les opérateurs >> et << pour la saisie et l’affichage.
Exercice n° :3
Soit une technique qui consiste à compter, en permanence, le nombre de références à un
emplacement (dynamique), c'est à dire le nombre de pointeurs le désignant à un moment
donné. Dans ces conditions, lorsqu'un objet est détruit, il suffit de n'en détruire la partie
dynamique que si son compteur de références est nul pour éviter les problèmes de risque de
libération multiple.
Pour mettre en œuvre cette technique, le compteur de références doit être mis à jour à chaque
fois que le nombre d'objets désignant l'emplacement correspondant risque d'être modifié.
Cela concerne donc:
Le constructeur par recopie: il doit initialiser un nouvel objet pointant sur un emplacement
déjà référence et donc incrémenter son compteur de références,
L'opérateur d'affectation; une instruction telle que a=b doit:
Décrémenter le compteur de références de l'emplacement référencé par a et procéder à
sa libération lorsque le compteur est nul,
Incrémenter le compteur de références de l'emplacement référencé par b.
Pour appliquer cette technique soit une classe vect dont la déclaration est la suivante:
# Include <iostream.h>
Struct element //structure de service pour la classe vect
{ int nref; //compteur de références
int *adr; // pointeur sur vecteur dynamique
};
Class vect
{ int nelem; //nombre de composantes du vecteur
element * adel; //pointeur sur partie dynamique
void decremente(); //fonction de service qui décrémente le compteur de
Public: //références et détruit si nécessaire
…
};
1°) Compléter la déclaration de la classe vect et donner sa définition, sachant qu'elle doit
disposer:
- d'un constructeur usuel,
- d'un constructeur par recopie,
- d'un destructeur,
- de la surdéfinition de l'opérateur d'affectation,
- de la surdéfinition de l'opérateur, qui permet l'accès à une des composantes du
vecteur,
Page n° :2/6
- une fonction d'affichage du vecteur,
- des impressions permettant de suivre l'évolution des compteurs et des appels des
fonctions membres.
2°) Ecrire une fonction main() qui permet de tester ces fonctions et ces opérateurs sur des
objets de la classe vect.
Exercice n° :4
1-Créer une classe "pile d’entiers naturels" de taille fixée à la création, et permettant les
opérations usuelles sur une pile :
main()
{ int x;
Pile_entier s(100),p; // tableau de 100 entiers
s.Empiler(10);
s.Affiche();
s.Empiler(20);
s.Affiche();
s.Empiler(30);
s.Affiche();
x=s.Depiler();
s.Affiche();
s.Empiler(s.Depiler());
s.Affiche();
if(s.NonVide()) x=s.Depiler();
s.Affiche();
s.Vide();
s.Affiche();
cin>>x;
while(s.Nonpleine()) s.Empiler(x);
s.Affiche();
p=s;
p.Affiche();
while(!s.Vide()) s.Depiler(x);
}
2- Reprendre le programme sur la pile d’entiers naturels, et essayer de trouver une notation
au moyen d’opérateurs et non plus de fonctions explicitement nommées "Empiler" ou
"Depiler".
Exercice n° :5
class Fraction
{
public:
Fraction();
Fraction(int i);
Fraction(int num,int den);
Fraction(Fraction &);
Fraction();
Page n° :3/6
Void affiche();
Fraction operator+ (const Fraction & f);
Fraction operator- (const Fraction & f);
Fraction operator* (const Fraction & f);
Fraction operator/ (const Fraction & f);
private:
int num,den;
void normalise();
};
Voici le rôle de chaque fonction :
Fraction(); : le constructeur par défaut initialise la fraction à 0.
Fraction(int); : initialise la fraction à l'entier i.
Fraction(int num, int den); : initialise le numérateur et le dénominateur de la fraction.
Fraction operator+ (const Fraction & f); permet de faire la somme de 2 fractions.
Fraction operator- (const Fraction & f); permet de faire la différence de 2 fractions.
Fraction operator*(const Fraction & f); permet de faire la multiplications de 2 fractions.
Fraction operator/ (const Fraction & f); permet de faire la division de 2 fractions.
void normalise() : normalise la fraction. Le dénominateur doit être positif et la fraction
irréductible.
Ecrire un programme principal qui saisit au clavier 2 fractions f1 et f2 et qui affiche
E=(f1+3/4-f2)/(f1*f2-5/8)+4.
Définir une nouvelle classe FRACTIONSIMP dérivant de FRACTION, mais dans laquelle
les nombres rationnels sont simplifiés. On prévoira:
- Un constructeur recevant en arguments le numérateur et le dénominateur d'un rationnel;
- Un constructeur par recopie;
- Une fonction membre privée(nommée pgcd) qui retourne le pgcd de deux entiers.
Exercice n° :6
1°) Définir une classe chaine permettant de créer et de manipuler une chaîne de caractères:
données:
- longueur de la chaîne (entier)
- adresse d’une zone allouée dynamiquement
méthodes:
- constructeur chaine() initialise une chaîne vide
- constructeur chaine(char *) initialise avec la chaîne passée en argument
- constructeur par recopie chaine(chaine &)
- opérateurs affectation (=), comparaison (==), concaténation (+), accès à un caractère de
rang donné ([])
Ecrire une fonction main() qui permet de tester ces fonctions et ces opérateurs sur des objets
de la classe chaine.
2°) Définir une classe chaine_nombre qui hérite de la classe chaine en s'intéressant
uniquement à des chaînes numériques:
données:
- la valeur numérique de la chaine (entier)
méthodes:
- constructeur chaine_nombre(char *) initialise la chaîne avec appel du constructeur de la
classe chaine
Page n° :4/6
- constructeur par recopie chaine_nombre(chaine &)
- fonction afficher (même nom que celui de la classe chaine)
Ecrire une fonction main() qui permet de tester ces fonctions sur des objets de la classe
chaine_nombre (essentiellement l'affichage d'un objet de la classe chaine_nombre comme un
objet de la classe chaine) .
Exercice n° :7
On désire manipuler des polynômes à une variable. Pour cela, on implémentera une instance
de la classe polynôme comme un tableau dynamique de monômes. Les monômes sont rangés
par degrés croissants.
Chacun des monômes est déclaré de type :
Typedef Struct
{ float coef;
int deg;
} Monome;
class polynome
{ Monome * poly;
int taille;
int nbelts;
public:
.....
};
il vous est demandé :
1. De spécifier complètement la classe polynôme.
2. D’implémenter les constructeurs et destructeur.
3. D’implémenter l’opérateur >, permettant d’indiquer si un degré d’un monôme figure
dans la liste des degrés du polynôme.
4. D’implémenter les deux opérateurs +, l’un permettant l’ajout physique d’un nouveau
monôme, l’autre permettant de construire la somme de deux polynômes.
5. D’implémenter les deux opérateurs -, l’un permettant la réalisation de la différence
d’un polynôme et un monôme, l’autre permettant de construire la différence de deux
polynômes.
6. D’implémenter l’opérateur d’affectation.
7. Surdéfinir les opérateurs >> et << pour la saisie et l’affichage.
8. D’implémenter la fonction nettoyer permettant de supprimer du tableau tout les
monômes à coefficient nul.
9. D’implémenter la fonction evaluer permettant d’évaluer un polynôme à une variable.
10. D’implémenter la fonction deriver permettant de déterminer la dérivée d'un polynôme
11. Mettre en œuvre cette classe dans main().
Exercice n° :8
On désire manipuler des polynômes à une variable . Pour représenter ceux-ci on propose une
structure de liste à simple chaînage:
Les monômes sont rangés par degrés croissants.
Chacun des monômes est déclaré de type :
Typedef Struct elt
{ float coef;
int deg;
Page n° :5/6
Struct elt * suiv ;
} Monome;
Class polynome
{ Monome * poly;
public: .....
};
La classe polynôme doit contenir entre autre :
1) Ajout d’un monôme au polynôme poly
ADMON(nom de fonction par exemple): le coefficient c et le degré d sont donnés en entrée
ainsi que le polynôme poly (supposé déjà construit) ADMON ajoute le monôme (c,d) au
polynôme poly.
2) Affichage d’un polynôme Cnxn + Cn-1xn-1 +...+C1x + C0 .
Envisager un format d'affichage adéquat.
3) L’opérateur + qui réalise la somme des deux polynômes.
4) Evaluation d'un polynôme à une variable
5) Détermination de la dérivée d'un polynôme
Mettre en œuvre cette classe dans main().
Page n° :6/6
Université Hassan II-Mohammedia Année Universitaire : 2014-15
Faculté des sciences Ben M’sik
Département des Maths et Informatique
Exercice n°:1
Soit une technique qui consiste à compter, en permanence, le nombre de références à un
emplacement (dynamique), c'est à dire le nombre de pointeurs le désignant à un moment
donné. Dans ces conditions, lorsqu'un objet est détruit, il suffit de n'en détruire la partie
dynamique que si son compteur de références est nul pour éviter les problèmes de risque de
libération multiple.
Pour mettre en œuvre cette technique, le compteur de références doit être mis à jour à chaque
fois que le nombre d'objets désignant l'emplacement correspondant risque d'être modifié.
Cela concerne donc:
Le constructeur par recopie: il doit initialiser un nouvel objet pointant sur un emplacement
déjà référence et donc incrémenter son compteur de références,
L'opérateur d'affectation; une instruction telle que a=b doit:
Décrémenter le compteur de références de l'emplacement référencé par a et procéder à
sa libération lorsque le compteur est nul,
Incrémenter le compteur de références de l'emplacement référencé par b.
Pour appliquer cette technique soit une classe vect dont la déclaration est la suivante:
# Include <iostream.h>
Struct element //structure de service pour la classe vect
{ int nref; //compteur de références
int *adr; // pointeur sur vecteur dynamique
};
Class vect
{ int nelem; //nombre de composantes du vecteur
element * adel; //pointeur sur partie dynamique
void decremente(); //fonction de service qui décrémente le compteur de
Public: //références et détruit si nécessaire
…
};
1°) Compléter la déclaration de la classe vect et donner sa définition, sachant qu'elle doit
disposer:
- d'un constructeur usuel,
- d'un constructeur par recopie,
- d'un destructeur,
- de la surdéfinition de l'opérateur d'affectation,
- de la surdéfinition de l'opérateur, qui permet l'accès à une des composantes du
vecteur,
- une fonction d'affichage du vecteur,
- des impressions permettant de suivre l'évolution des compteurs et des appels des
fonctions membres.
2°) Ecrire une fonction main() qui permet de tester ces fonctions et ces opérateurs sur des
objets de la classe vect.
Page n° :1/4
Exercice n° 2:
1-Créer une classe "pile d’entiers naturels" de taille fixée à la création, et permettant les
opérations usuelles sur une pile :
main()
{ int x;
Pile_entier s(100),p; // tableau de 100 entiers
s.Empiler(10);
s.Affiche();
s.Empiler(20);
s.Affiche();
s.Empiler(30);
s.Affiche();
x=s.Depiler();
s.Affiche();
s.Empiler(s.Depiler());
s.Affiche();
if(s.NonVide()) x=s.Depiler();
s.Affiche();
s.RAZ();
s.Affiche();
cin>>x;
while(s.Nonpleine()) s.Empiler(x);
s.Affiche();
p=s;
p.Affiche();
while(!s.Vide()) s.Depiler(x);
}
2- Reprendre le programme sur la pile d’entiers naturels, et essayer de trouver une notation
au moyen d’opérateurs et non plus de fonctions explicitement nommées "Empiler" ou
"Depiler".
Exercice n° 3:
class Fraction
{
public:
Fraction();
Fraction(int i);
Fraction(int num,int den);
Fraction(Fraction &);
Fraction();
Void affiche();
Fraction operator+ (const Fraction & f);
Fraction operator- (const Fraction & f);
Fraction operator* (const Fraction & f);
Page n° :2/4
Fraction operator/ (const Fraction & f);
private:
int num,den;
void normalise();
};
Voici le rôle de chaque fonction :
Fraction(); : le constructeur par défaut initialise la fraction à 0.
Fraction(int); : initialise la fraction à l'entier i.
Fraction(int num, int den); : initialise le numérateur et le dénominateur de la fraction.
Fraction operator+ (const Fraction & f); permet de faire la somme de 2 fractions.
Fraction operator- (const Fraction & f); permet de faire la différence de 2 fractions.
Fraction operator*(const Fraction & f); permet de faire la multiplications de 2 fractions.
Fraction operator/ (const Fraction & f); permet de faire la division de 2 fractions.
void normalise() : normalise la fraction. Le dénominateur doit être positif et la fraction
irréductible.
Ecrire un programme principal qui saisit au clavier 2 fractions f1 et f2 et qui affiche
E=(f1+3/4-f2)/(f1*f2-5/8)+4.
Définir une nouvelle classe FRACTIONSIMP dérivant de FRACTION, mais dans laquelle
les nombres rationnels sont simplifiés. On prévoira:
- Un constructeur recevant en arguments le numérateur et le dénominateur d'un rationnel;
- Un constructeur par recopie;
- Une fonction membre privée(nommée pgcd) qui retourne le pgcd de deux entiers.
Exercice n°:4
1°) Définir une classe chaine permettant de créer et de manipuler une chaîne de caractères:
données:
- longueur de la chaîne (entier)
- adresse d’une zone allouée dynamiquement
méthodes:
- constructeur chaine() initialise une chaîne vide
- constructeur chaine(char *) initialise avec la chaîne passée en argument
- constructeur par recopie chaine(chaine &)
- opérateurs affectation (=), comparaison (==), concaténation (+), accès à un caractère de
rang donné ([])
Ecrire une fonction main() qui permet de tester ces fonctions et ces opérateurs sur des objets
de la classe chaine.
2°) Définir une classe chaine_nombre qui hérite de la classe chaine en s'intéressant
uniquement à des chaînes numériques:
données:
- la valeur numérique de la chaine (entier)
méthodes:
- constructeur chaine_nombre(char *) initialise la chaîne avec appel du constructeur de la
classe chaine
- constructeur par recopie chaine_nombre(chaine &)
- fonction afficher (même nom que celui de la classe chaine)
Page n° :3/4
Ecrire une fonction main() qui permet de tester ces fonctions sur des objets de la classe
chaine_nombre (essentiellement l'affichage d'un objet de la classe chaine_nombre comme un
objet de la classe chaine) .
Exercice n°:5
On désire manipuler des polynômes à une variable . Pour représenter ceux-ci on propose une
structure de liste à simple chaînage:
Les monômes sont rangés par degrés croissants.
Chacun des monômes est déclaré de type :
Typedef Struct elt
{ float coef;
int deg;
Struct elt * suiv ;
} Monome;
Class polynome
{ Monome * poly;
public: .....
};
Page n° :4/4
Université Hassan II-Mohammedia Année Universitaire : 2010-11
Faculté des sciences Ben M’sik
Département des Maths et Informatique
Exercice n° :1
class complexe
{
float re,im; // partie réelle (re) et imaginaire (im) du nombre complexe
public:
complexe(float reel, float imaginaire = 0); // constructeur
float real(); // fonction qui retourne la partie réelle
float imag(); // fonction qui retourne la partie imaginaire
float norme(); // fonction qui retourne la norme d'un complexe
void affiche(); // fonction qui affiche les membres données d'un complexe
complexe conjugue(); // fonction qui retourne le conjugué d'un complexe
complexe somme(complexe); // fonction qui retourne la somme de deux
complexes
complexe difference(complexe); // fonction qui retourne la soustraction de deux
complexes
complexe produit(complexe); // fonction qui retourne le produit de deux
complexes
};
Définir toutes les méthodes de cette classe, et les mettre en œuvre dans main().
Page n° : 1/3
Exercice n° :2
Réaliser une classe RAT implantant le type nombre rationnel. On prévoira:
1. Un constructeur recevant en arguments le numérateur et le dénominateur d'un
rationnel et normalise son signe de façon à ce que, si le rationnel est négatif, le
signe se trouve au niveau du numérateur;
2. Deux fonctions membres publiques (nommées numérateur et dénominateur)
fournissant en retour respectivement le numérateur et le dénominateur d'un
rationnel;
3. Des fonctions multiplication et division qui permettent la multiplication et la
division de deux rationnels;
4. Des fonctions somme et soustraction qui permettent l'addition et la soustraction
de deux rationnels;
5. Des membres données qui sont le numérateur et le dénominateur du rationnel.
Ecrire une fonction main() qui permet de tester ces fonctions et ces opérateurs sur
des objets de la classe RAT.
Exercice n° :3
class Fraction
{
public:
Fraction();
Fraction(int i);
Fraction(int num,int den);
Fraction(Fraction &);
Fraction();
Void affiche();
Fraction somme (const Fraction & f);
Fraction difference(const Fraction & f);
Fraction produit(const Fraction & f);
Fraction division(const Fraction & f);
private:
int num,den;
int pgcd(int x, int y);
void normalise();
};
Voici le rôle de chaque fonction :
Fraction(); : le constructeur par défaut initialise la fraction à 0.
Fraction(int); : initialise la fraction à l'entier i.
Fraction(int num, int den); : initialise le numérateur et le dénominateur de la
fraction.
Page n° : 2/3
Fraction somme(const Fraction & f); permet de faire la somme de 2 fractions.
Fraction difference(const Fraction & f); permet de faire la différence de 2 fractions.
Fraction produit(const Fraction & f); permet de faire la multiplications de 2
fractions.
Fraction divition(const Fraction & f); permet de faire la division de 2 fractions.
int pgcd(int x, int y) : calcule le pgcd de 2 entiers.
void normalise() : normalise la fraction. Le dénominateur doit être positif et la
fraction irréductible.
Ecrire un programme principal qui saisit au clavier 2 fractions f1 et f2 et qui affiche
E=(f1+3/4-f2)/(f1*f2-5/8)+4.
Exercice n° :4
class pile_entier
{int *pile,taille,hauteur; // pointeur de pile, taille maximum, hauteur actuelle
public:pile_entier(int); // constructeur, taille de la pile, 20 par defaut, initialise la
hauteur à 0 alloue dynamiquement de la place mémoire
~pile_entier(); // destructeur
void empile(int); // ajoute un élement
int depile(); // retourne la valeur de l’entier en haut de la pile, la hauteur
// diminue de 1 unité
int pleine(); // retourne 1 si la pile est pleine, 0 sinon
int vide(); // retourne 1 si la pile est vide, 0 sinon
};
Définir toutes les méthodes de cette classe, et les mettre en œuvre dans main().
Page n° : 3/3
Université Hassan II-Mohammedia Année Universitaire : 2010-11
Faculté des sciences Ben M’sik
Département des Maths et Informatique
Exercice n°:1
Définir une classe chaine permettant de créer et de manipuler une chaîne de caractères:
données:
- longueur de la chaîne (entier)
- adresse d’une zone allouée dynamiquement
méthodes:
- constructeur chaine() initialise une chaîne vide
- constructeur chaine(char *) initialise avec la chaîne passée en argument
- constructeur par recopie chaine(chaine &)
- opérateurs affectation (=), comparaison (==), concaténation (+), accès à un caractère de
rang donné ([])
Ecrire une fonction main() qui permet de tester ces fonctions et ces opérateurs sur des objets
de la classe chaine.
Exercice n°:2
1-Créer une classe "pile d’entiers naturels" de taille fixée à la création, et permettant les
opérations usuelles sur une pile :
main()
{ int x;
Pile_entier s(100),p; // tableau de 100 entiers
s.Empiler(10);
s.Affiche();
s.Empiler(20);
s.Affiche();
s.Empiler(30);
s.Affiche();
x=s.Depiler();
s.Affiche();
s.Empiler(s.Depiler());
s.Affiche();
if(s.NonVide()) x=s.Depiler();
s.Affiche();
s.Vide();
s.Affiche();
cin>>x;
while(s.Nonpleine()) s.Empiler(x);
s.Affiche();
p=s;
p.Affiche();
while(!s.Vide()) s.Depiler(x);
}
2- Reprendre le programme sur la pile d’entiers naturels, et essayer de trouver une notation
au moyen d’opérateurs et non plus de fonctions explicitement nommées "Empiler" ou
"Depiler".
Exercice n°:3
On souhaite manipuler des ensembles d’entiers sans doublon (chaque élément doit être
unique). Pour cela, on implémentera une instance de la classe Ensemble comme un tableau
dynamique d’entiers (le nombre effectif d’éléments du tableau sera toujours égal au cardinal
de l’ensemble), comme suit :
Class Ensemble
{
private :
in *tab ;
int taille;
int nbelts ;
public:
--------
};
Sachant qu’on désire pouvoir effectuer toutes les opérations figurant dans le main() suivant,
il vous est demandé :
1. De spécifier complètement la classe Ensemble
2. D’implémenter les constructeurs et destructeur.
3. D’implémenter les deux opérateurs >,l’un permettant d’indiquer si un ensemble
contient un élément particulier, l’autre permettant d’indiquer si un ensemble contient
un autre ensemble .
4. D’implémenter les deux opérateurs +, l’un permettant l’ajout physique d’un nouvel
élément, l’autre permettant de construire l’union de deux ensembles.
5. D’implémenter l’opérateur d’affectation
# include <iostream.h>
………..
………..
main()
{
Ensemble e1;// e est initialisé à vide
if (e1.estvidde()) // test si e1 est vide
cout<< " e1 est vide ";
else
cout<< "e1 n’est pas vide" ;
e2 + 17 ; // l’entier 17 est ajouté physiquement à e2, s’il n’est pas déjà présent dans e2
e2 + 11 ; // l’entier 11 est ajouté physiquement à e2, s’il n’est pas déjà présent dans e2
e2 + 3 ; // l’entier 3 est ajouté physiquement à e2, s’il n’est pas déjà présent dans e2
e1 + 7 ; // l’entier 7 est ajouté physiquement à e1, s’il n’est pas déjà présent dans e1
cout << e2; // les éléments de e2 sont affichés à l’écran
Ensemble e3,e4;
e3=e1+e2 ; // e3 est l’union de e1 et e2 (sans doublon)
if (e2 > e1) // si l’ensemble e2 contient l’ensemble e1 (tout élément de e1 appartient à e2)
cout << "e2 contient e1 " ;
else
cout << "e2 ne contient pas e1 " ;