La classe que nous allons réaliser n'est pas très compliquée. Et il est assez aisé d'imaginer quelles méthodes et opérateurs nous allons utiliser. Cet exercice va en particulier tester vos connaissances sur :
- Les attributs et leurs droits d'accès.
- Les constructeurs.
- La surcharge des opérateurs.
C'est donc le dernier moment de réviser !
Description de la classe ZFraction
Commençons par choisir un nom pour notre classe. Ce serait bien qu'il contienne le mot "fraction" et comme vous êtes sur le site du zéro, je vous propose d'ajouter un "Z" au début. Ce sera donc
ZFraction. Ce n'est pas super original, mais au moins on sait directement à quoi on a affaire.
Utiliser des
int ou des
double est très simple. On les déclare, on les initialise et on utilise ensuite les opérateurs comme sur une calculatrice. Ce serait vraiment super de pouvoir faire la même chose pour des fractions.
On aimerait donc bien que le
main() suivant compile et fonctionne correctement :
Code : C++ - Utilisation de ZFraction 1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27 | #include <iostream>
#include "ZFraction.h"
using namespace std;
int main()
{
ZFraction a(4,5); //Déclare une fraction valant 4/5
ZFraction b(2); //Déclare une fraction valant 2/1 (ce qui vaut 2)
ZFraction c,d; //Déclare deux fractions valant 0
c = a+b; //Calcule 4/5 + 2/1 = 14/5
d = a*b; //Calcule 4/5 * 2/1 = 8/5
cout << a << " + " << b << " = " << c << endl;
cout << a << " * " << b << " = " << d << endl;
if(a > b)
cout << "a est plus grand que b." << endl;
else if(a==b)
cout << "a est egal a b." << endl;
else
cout << "a est plus petit que b." << endl;
return 0;
}
|
Et voici le résultat espéré :
Code : Console | 4/5 + 2 = 14/5
4/5 * 2 = 8/5
a est plus petit que b. |
Pour arriver à cela, il nous faudra donc :
- Écrire la classe avec ses attributs.
- Réfléchir aux constructeurs à implémenter.
- Surcharger les opérateurs +, *, <<, < et == (au moins).
En maths, lorsque l'on manipule des fractions, on utilise toujours des fractions simplifiées. C'est-à-dire que l'on écrira

plutôt que

même si ces deux fractions ont la même valeur. Il faudra donc faire en sorte que notre classe
ZFraction respecte cette règle.
Si vous vous sentez prêt, alors allez-y ! Je n'ai rien de plus à ajouter concernant la donnée. Vous pourrez trouver certains rappels sur les calculs avec les nombres rationnels dans le
cours de maths disponible sur ce site.
Si par contre vous avez peur de vous lancer seul, je vous propose de vous accompagner pour les premiers pas.
Créer un nouveau projet
Pour faire ce TP, vous allez devoir créer un nouveau projet. Utilisez l'IDE que vous voulez, moi pour ma part vous savez que j'utilise Code::Blocks
Demandez à créer un nouveau
projet console C++.
Ce projet sera constitué de 3 fichiers que vous pouvez déjà créer :
- main.cpp : ce fichier contiendra uniquement la fonction main. Dans la fonction main, nous créerons des objets basés sur notre classe ZFraction pour tester son fonctionnement. A la fin, votre fonction main() devra ressembler à celle que je vous ai montré plus haut.
- ZFraction.h : ce fichier contiendra le prototype de notre classe ZFraction avec la liste de ses attributs et les prototypes de ses méthodes.
- ZFraction.cpp : ce fichier contiendra l'implémentation des méthodes de la classe ZFraction, c'est-à-dire le "code" à l'intérieur des méthodes.
Faites attention aux noms des fichiers et en particulier aux majuscules et minuscules. Les fichiers ZFraction.h et ZFraction.cpp commencent par 2 lettres majuscules, si vous écrivez "zfraction" ou encore "Zfraction" ça ne marchera pas et vous aurez des problèmes.
Le code de base des fichiers
Nous allons écrire un peu de code dans chacun de ces fichiers. Juste le strict minimum pour pouvoir commencer.
main.cpp
Bon, celui-là, je vous l'ai déjà donné.
Mais pour commencer en douceur, je vous propose de simplifier l'intérieur de la fonction
main() et d'y ajouter des instructions petit-à-petit au fur et à mesure de l'avancement de votre classe.
Code : C++ - main.cpp | #include <iostream>
#include "ZFraction.h"
using namespace std;
int main()
{
ZFraction a(1,5); // Crée une fraction valant 1/5
return 0;
}
|
Pour l'instant, on se contente d'un appel au constructeur de
ZFraction. Pour le reste, on verra plus tard.
ZFraction.h
Ce fichier contiendra la définition de la classe
ZFraction. Il inclut aussi
iostream pour nos besoins futurs (nous aurons besoin de faire des
cout dans la classe les premiers temps, ne serait-ce que pour débugger notre classe).
Code : C++ - ZFraction.h 1
2
3
4
5
6
7
8
9
10
11
12
13
14 | #ifndef DEF_FRACTION
#define DEF_FRACTION
#include <iostream>
class ZFraction
{
public:
private:
};
#endif
|
Pour l'instant, la classe est encore vide. Je ne vais pas non plus tout vous faire hein ! J'y ai quand même mis une partie privée et une partie publique. Souvenez-vous de la règle principale de la POO qui veut que tous les attributs soient dans la partie privée. Je vous en voudrais beaucoup si vous ne la respectiez pas.
Comme tous les fichiers .h, ZFraction.h contient deux lignes commençant par # au début du fichier et une autre tout à la fin. Code::Blocks crée automatiquement ces lignes. Si votre IDE ne le fait pas, pensez à les ajouter. Elles évitent bien des soucis de compilation.
ZFraction.cpp
C'est le fichier qui va contenir les définitions des méthodes. Comme notre classe est encore vide, il n'y a donc rien à y écrire. Il faut juste penser à inclure l'entête
ZFraction.h.
Code : C++ - ZFraction.cpp
Nous voilà enfin prêt à attaquer la programmation !
Choix des attributs de la classe
La première étape de la création d'une classe est souvent le choix des attributs. Il faut se demander de quelles briques de base notre classe est constituée. Avez-vous une petite idée ?
Voyons ça ensemble. Un nombre rationnel est composé de deux nombres entiers appelés le numérateur (celui qui est au-dessus de la barre de fraction) et le dénominateur (celui du dessous). Cela nous fait donc deux constituants. Les nombres entiers en C++ s'appellent des
int. Ajoutons donc deux
int à notre classe :
Code : C++ - ZFraction.h 1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17 | #ifndef DEF_FRACTION
#define DEF_FRACTION
#include <iostream>
class ZFraction
{
public:
private:
int m_numerateur; //Le numérateur de la fraction
int m_denominateur; //Le dénominateur de la fraction
};
#endif
|
Nos attributs commencent toujours par le préfixe "m_". C'est une bonne habitude de programmation que je vous ai enseignée dans les chapitres précédents

Cela nous permettra par la suite de savoir si on est en train de manipuler un attribut de la classe ou une simple variable "locale" à une méthode.
Les constructeurs
Je ne vais pas tout vous dire non plus, mais dans le
main() d'exemple que je vous ai présenté tout au début, on utilisait trois constructeurs différents :
- Le premier recevait deux entiers comme argument. Ils représentaient respectivement le numérateur et le dénominateur de la fraction. C'est sans doute le plus intuitif des trois à écrire.
- Le deuxième constructeur prend un seul entier en argument et construit une fraction égale à ce nombre entier. Cela veut dire que le dénominateur vaut 1 dans ce cas.
- Finalement, le dernier constructeur ne prend aucun argument (constructeur par défaut) et crée une fraction valant 0.
Je ne vais rien expliquer de plus. Je vous propose de commencer par écrire au moins le premier de ces trois constructeurs. Les autres suivront rapidement, j'en suis sûr.
Les opérateurs
La part la plus importante de ce TP sera l'implémentation des opérateurs. Il faut bien réfléchir à la manière de les écrire. Vous pouvez bien sûr vous inspirer de ce qui a été fait pour la classe
Duree du chapitre précédent. Par exemple, utiliser la méthode
operator+= pour définir l'opérateur +. Ou écrire une méthode
estEgalA() pour l'opérateur d'égalité.
Une bonne chose à faire est de commencer par l'opérateur <<. Vous pourrez alors facilement tester vos autres opérateurs.
Simplifier les fractions
L'important avec les fractions est de toujours manipuler des fractions simplifiées. C'est-à-dire que l'on va préférer écrire

que

par exemple. Il serait bien que notre classe fasse de même et simplifie elle-même la fraction qu'elle représente.
Il nous faut donc un moyen mathématique de le faire puis traduire le tout en C++. Si l'on a une fraction

, il faut calculer le plus grand commun diviseur de

et

puis diviser

et

par ce nombre. Par exemple, le
pgcd de

et

est

, ce qui veut dire que l'on peut simplifier les numérateurs et dénominateurs de

par

, ce qui nous fait bien

.
Calculer le pgcd n'est pas une opération facile. Je vous propose donc une fonction pour le faire. Je vous invite à l'ajouter dans votre fichier
ZFraction.cpp.
Code : C++ - Fonction de calcul du pgcd | int pgcd(int a, int b)
{
while (b != 0)
{
const int t = b;
b = a%b;
a=t;
}
return a;
}
|
Et à ajouter le prototype correspondant dans
ZFraction.h :
Code : C++ - ZFraction.h 1
2
3
4
5
6
7
8
9
10
11
12
13 | #ifndef DEF_FRACTION
#define DEF_FRACTION
#include <iostream>
class ZFraction
{
//Contenu de la classe...
};
int pgcd(int a, int b);
#endif
|
Vous pourrez alors utiliser cette fonction dans les méthodes de la classe.
Allez au boulot !