Partage
  • Partager sur Facebook
  • Partager sur Twitter

Classe et operateur

besoin d'un conseil d'amelioration

Sujet résolu
    5 mai 2008 à 12:22:00


    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! :euh:
    je debute, et ma solution me semble un peu longue!!

    qu'en pensez vous?
    tout commentaire est le bienvenue, merci d'avance :)
    • Partager sur Facebook
    • Partager sur Twitter
    Tout ce que le seigneur fait, il le fait pour le bien
      5 mai 2008 à 13:11:08

      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
      	
      };
      
      • Partager sur Facebook
      • Partager sur Twitter
        5 mai 2008 à 13:28:25

        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.

        • Partager sur Facebook
        • Partager sur Twitter
        Tout ce que le seigneur fait, il le fait pour le bien
          5 mai 2008 à 14:25:58

          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.
          • Partager sur Facebook
          • Partager sur Twitter
          C++: Blog|FAQ C++ dvpz|FAQ fclc++|FAQ Comeau|FAQ C++lite|FAQ BS| Bons livres sur le C++| PS: Je ne réponds pas aux questions techniques par MP.
            5 mai 2008 à 15:05:29

            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 :D
            • Partager sur Facebook
            • Partager sur Twitter
            Tout ce que le seigneur fait, il le fait pour le bien
              5 mai 2008 à 15:20:27

              Non. Affecte tes deux parties simultanément. Les manipuler unitairement n'a aucun sens -- en plus d'être inefficace.
              • Partager sur Facebook
              • Partager sur Twitter
              C++: Blog|FAQ C++ dvpz|FAQ fclc++|FAQ Comeau|FAQ C++lite|FAQ BS| Bons livres sur le C++| PS: Je ne réponds pas aux questions techniques par MP.
                5 mai 2008 à 17:32:09

                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 o_O !!
                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 :lol:

                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) :euh: ,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!!! :)

                • Partager sur Facebook
                • Partager sur Twitter
                Tout ce que le seigneur fait, il le fait pour le bien
                  5 mai 2008 à 17:51:16

                  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.
                  • Partager sur Facebook
                  • Partager sur Twitter
                  C++: Blog|FAQ C++ dvpz|FAQ fclc++|FAQ Comeau|FAQ C++lite|FAQ BS| Bons livres sur le C++| PS: Je ne réponds pas aux questions techniques par MP.

                  Classe et operateur

                  × 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.
                  • Editeur
                  • Markdown