Salut tout le monde,
j'ai un petit exercice tres typique sur les classes: creer une classe permettant de stocker des nombres a fraction.
je pense avoir resolu l'exercice, tout marche sur des roulettes, et tout compil comme prevu, seulement je ne suis pas trop satisfait de mon programme. Il me semble beaucoup trop long et compliqué.
voici la classe:
class RationalNumber
{
int m_num, m_denum;
RationalNumber simplify();
public:
RationalNumber();
RationalNumber(int);
RationalNumber(int, int);
void setNum(int);
void setDenum(int);
int getNum();
int getDenum();
void print();
bool equal (RationalNumber&);
RationalNumber operator+(const RationalNumber&);
RationalNumber operator-(const RationalNumber&);
RationalNumber operator/(const RationalNumber&);
RationalNumber operator*(const RationalNumber&);
};
et voici mes declarations:
/* Declarations des constructeurs */
RationalNumber :: RationalNumber() :m_num(0), m_denum(1){} // Constructeur par defaut
RationalNumber :: RationalNumber(int num) : m_num(num), m_denum(1) {} //Constructeur dont le numerateur est demandé mais le denominateur est par defaut
RationalNumber :: RationalNumber(int num, int denum) : m_num(num), m_denum(denum) {} //Constructeur dont le numerateur et le denominateur sont demandés
/* Declaration des fonctions */
/* Fonctions SET */
void RationalNumber :: setNum (int num)
{
m_num = num;
}
void RationalNumber :: setDenum (int denum)
{
if (denum != 0)
m_denum = denum;
}
/* Fonctions Get */
int RationalNumber :: getNum()
{
return m_num;
}
int RationalNumber :: getDenum()
{
return m_denum;
}
/* Autres fonctions */
RationalNumber RationalNumber :: simplify ()
{
int numTmp = m_num,
denumTmp = m_denum,
rest;
do{
rest = numTmp % denumTmp;
if (rest != 0)
denumTmp=rest;
}while (rest);
m_num /= denumTmp;
m_denum /= denumTmp;
return *(this);
}
bool RationalNumber :: equal ( RationalNumber &numb2)
{
simplify ();
numb2.simplify();
if (m_num == numb2.getNum() && m_denum == numb2.getDenum())
return 1;
else
return 0;
}
void RationalNumber :: print()
{
cout <<m_num << "/"<<m_denum <<endl;
}
/* Declarations des operateurs */
RationalNumber RationalNumber :: operator+ (const RationalNumber &num2)
{
int new_num = ( (m_num* num2.m_denum) + (num2.m_num*m_denum) );
int new_denum = (m_denum * num2.m_denum);
m_num=new_num;
m_denum=new_denum;
simplify();
return *this;
}
RationalNumber RationalNumber :: operator- (const RationalNumber &num2)
{
int new_num = ( (m_num* num2.m_denum) - (num2.m_num*m_denum) );
int new_denum = (m_denum * num2.m_denum);
m_num=new_num;
m_denum=new_denum;
simplify();
return *this;
}
RationalNumber RationalNumber :: operator* (const RationalNumber &num2)
{
m_num = (m_num* num2.m_num);
m_denum = (m_denum * num2.m_denum);
simplify();
return *this;
}
RationalNumber RationalNumber :: operator/ (const RationalNumber &num2)
{
m_num = (m_num* num2.m_denum);
m_denum = (m_denum * num2.m_num);
simplify();
return *this;
}
Ce qui me derange en faite, c'est que j'ai l'impression de ne pas m'etre servi des atouts du c++.
j'aurai par exemple preféré faire des operateurs une fonction ami de la classe.
Enfin, je sais pas trop!
je debute, et ma solution me semble un peu longue!!
qu'en pensez vous?
tout commentaire est le bienvenue, merci d'avance
Tout ce que le seigneur fait, il le fait pour le bien
class RationalNumber
{
int m_num, m_denum; //RQ: tu peux mettre le numerateur en public, car tu fais aucun contrôle dessus, mais c'est pas obligatoire
RationalNumber simplify(); //OK
public:
RationalNumber();//
RationalNumber(int);//
RationalNumber(int, int);
// tu peux simplifier tes 3 constructeurs en un seul avec les valeurs par defaut :
// RationalNumber(int num = 0, int den = 1);
//Tu peux aussi définir un constructeur à partir d'un double mais ca risque d'être compliqué (3.14 = 314/100)
void setNum(int);
void setDenum(int);
int getNum();
int getDenum();
//OK
void print(); // OK mais ca serait mieux de redefinir l'opérateur de flux. en friend
bool equal (RationalNumber&); // OK mais ca serait mieux de redéfinir l'opérateur ==
RationalNumber operator+(const RationalNumber&);
RationalNumber operator-(const RationalNumber&);
RationalNumber operator/(const RationalNumber&);
RationalNumber operator*(const RationalNumber&);
//OK
};
Avant tout, merci pour ta réponse. Qui dailleur me force a te poser une question suplementaire.
class RationalNumber
{
int m_num, m_denum; //RQ: tu peux mettre le numerateur en public, car tu fais aucun contrôle dessus, mais c'est pas obligatoire
RationalNumber simplify(); //OK
On nous a enseigner que l'on devait s'efforcer de mettre un maximum de membre d'une classe en private?
En ce qui concerne les constructeurs, merci. Voila qui allege deja un peut tout ca.
Tout ce que le seigneur fait, il le fait pour le bien
Les mutateurs ne servent à rien dans ce cas.
Les accesseurs ne sont pas const-corrects.
Les opérateurs binaires ne sont ni const-corrects, ni symétriques.
Les opérateurs auto-modifiants ont été oubliés.
Cf l'interface de std::complex (http://dinkumware.com/manuals/default.aspx?manual=compleat&page=complex.html#complex), ou celle de boost.rational (http://www.boost.org/doc/libs/1_35_0/libs/rational/index.html) pour voir à quoi cela devrait ressembler.
Merçi pour ta réponse lmghs.
Pour ce qui est des mutateurs, on ne le vois pas dans ce que j'ai envoyé, mais mon main() demande a l'utilisateur de rentrer de nouvelles valeurs pour le numerateur et le denominateur.
Pour changer les valeurs, je pense que c'est la seule solution possible,non?
je vais faire un tour sur le lien que tu m'a envoyé.
Merci
Tout ce que le seigneur fait, il le fait pour le bien
Ok! lmghs, j'ai fais ce que tu m'a dis a propo des mutateurs. Je suis allez faire un tour sur le site que tu m'a envoyé, et a vrai dire.... ma reaction a été plutot du genre !!
C'est super compliqué ce qu'il y a la bas, je suis pas encore de ce niveau la, moi!
Mais, bon, en tout cas ca m'a permis de comprendre que une chose, a priori simple comme une fraction, cache de nombreuses lignes de code
ledemonboiteux, pour les constructeurs, je pense que j'ai besoin des 3, au cas où l'utilisateur ne rentrerai pas toutes les valeurs (C.A.D: numerateur et denominateur) ,non?
Et une derniere question les gars!
je voulais mettre mes operateurs en fonction globale, et j'ai vu sur le lien que lmghs m'a envoyé qu'ils ont été défini comme je l'ai fait. On en arrive à la question: POURQUOI???. Existe il une regle a connaitre??
Voili,voila, merçi pour votre aide!!!
Tout ce que le seigneur fait, il le fait pour le bien
ledemonboiteux te signalait que tu peux à la place ne définir qu'un seul constructeur et utiliser des valeurs par défaut. boost.rational a choisit d'en avoir trois pour éviter d'appliquer des transformations que l'on sait inutiles (pas besoin de noramilser si le dénominateur est celui par défaut, à savoir 1).
Sur les deux sites, tous les opérateurs binaires sont libres (pas membre)(définitions cachées dans un autre fichier). Les auto-modifiants (pas de meilleur nom qui me viennent à l'esprit pour l'instant pour désigner, +=, *=, -=, et /=) sont quant à eux membre.
Cf mes interventions passés sur le sujet, notamment dans les commentaires des 2 tutos en rapport.
× Après avoir cliqué sur "Répondre" vous serez invité à vous connecter pour que votre message soit publié.
× Attention, ce sujet est très ancien. Le déterrer n'est pas forcément approprié. Nous te conseillons de créer un nouveau sujet pour poser ta question.
* Un wrapper C++ pour sqlite * Une alternative a boost units