Probleme de surcharge d'opérateur et de fonction amies

Probleme de surcharge d'opérateur et de fonction amies - C++ - Programmation

Marsh Posté le 27-09-2007 à 18:32:47    

Bonjour, j'aurais besoin d'explication pour mon programme. Voici la situation , j'aimerais en gros réaliser les operations suivantes :
 

Code :
  1. /*******************************test.cc***********************/
  2. Longueur L(100); 
  3. Temps T (10); 
  4. Vitesse V (40);
  5. double d;
  6. L= V * T;    ==>ok
  7. V = V * 2;  ==>ne marche pas
  8. V = V * V  ==>ok
  9. V = 2 * V;  ==>ok
  10. d = V * V;  ==>ne marche pas


 
J'ai donc deux problémes que je n'arrive pas à résoudre, voici mon code :  
 

Code :
  1. /*******************************grandeur.h***********************/
  2. template <typename TYPE>
  3. class Grandeur{
  4. Grandeur(double tval=0):val(tval){};
  5. public:
  6.   Grandeur(double tval=0):val(tval){};
  7.   inline double getVal() const{
  8.     return val;
  9.   }
  10.   friend inline TYPE operator * (const TYPE& t1,const TYPE& t2){
  11.     return TYPE(t1.val * t2.val);
  12.   }
  13. protected:
  14.   double val;
  15. };
  16. class Longueur : public Grandeur<Longueur>{
  17. public:
  18. Longueur(double tval=0):Grandeur<Longueur>(tval){}
  19. };
  20. class Temps : public Grandeur<Temps>{
  21. public:
  22. Temps(double tval=0):Grandeur<Temps>(tval){}
  23. };
  24. class Vitesse : public Grandeur<Vitesse>{
  25. public:
  26. Vitesse(double tval=0):Grandeur<Vitesse>(tval){}
  27.   Longueur operator * (const Temps& t) const;
  28. };
  29. inline Longueur Vitesse::operator * (const Temps& t) const{
  30.   return Longueur(val * t.getVal());
  31.   }


 
 
Déjà je ne comprend pas vraiment pourquoi V = 2 * V me rend un resultat correct puisque d'apres ce que j'ai compris une classe fille ne peut pas se servir des fonctions amies de la classe mére ??? mais il me fallait des fonctions non membre pour réaliser cette opération.
 
Pour V = V * 2 par contre, le compilateur me sort :
 
 erreur: ambiguous overload for ‘operator*’
 note: candidats sont: Longueur Vitesse::operator*(const Temps& ) const
 note:                 Vitesse operator*(const Vitesse&, const Vitesse& )
 
Le nombre ne connait donc pas son type de convertion, c'est donc mon modéle qui est faux mais je ne voit pas comment organiser les choses différemment. Je pensais a surcharger l'operateur de convertion des doubles sinon, dans la classe générique :
 
 

Code :
  1. TYPE operateur double(){
  2.     return TYPE(val);
  3.   }


 
mais le compilateur n'aime pas apparemment ...
 
Le dernier test d = V * V reste un mystére, j 'ai l'erreur suivante :
erreur: cannot convert ‘Vitesse’ to ‘double’ in assignment
 
Je ne comprend pas pourquoi le double n'est pas transformer en une instance de Vitesse, puisqu'il le fait très bien lors de la multiplication 2*V , j'ai donc essayé de réécrire l'opérateur d'affectation mais toujours rien ...
 
Donc voilà je ne sais plus trop quoi faire et une petite aide serait la bien venue, merci d'avance  
 

Reply

Marsh Posté le 27-09-2007 à 18:32:47   

Reply

Marsh Posté le 27-09-2007 à 19:08:09    

[icode]operator double()[/icode] doit renvoyer un double
 
ca reglera ton dernier test...
 
----
note: pour la balise, http://kangol.prout.be/gm/md_inlinecode.user.js

Reply

Marsh Posté le 27-09-2007 à 19:20:34    

ca régle quoi en fait ? je comprend pas trop le principe

Reply

Marsh Posté le 27-09-2007 à 19:25:05    

bha vu que tu lui dit comment convertir en double, il le sais ...

Reply

Marsh Posté le 27-09-2007 à 19:31:36    

mais en fait ce que je voulais en faisant ça c'était de contourner l'ambiguitée qu'il y avait en transformant un double en un élément de la classe fille , ca ne m'intéresse pas de convertir en double . Je dois m'être mal organisé dans l'héritage ou je ne sais quoi, je bloque complétement ...

Reply

Marsh Posté le 27-09-2007 à 19:37:55    

fais des typedef, ca ira plus vite :o

Reply

Marsh Posté le 27-09-2007 à 19:46:32    

ou ca des typedef ?

Reply

Marsh Posté le 27-09-2007 à 19:58:02    

tu me copieras 10000 fois :
 
"les operateurs binaires ne s'implantent pas comme des fonctions firends masi comme des fonctiosn libres" :o

Reply

Marsh Posté le 27-09-2007 à 20:03:34    

Joel F a écrit :

tu me copieras 10000 fois :
 
"les operateurs binaires ne s'implantent pas comme des fonctions firends masi comme des fonctiosn libres" :o


Et pourquoi pas des friends?

Reply

Marsh Posté le 27-09-2007 à 20:06:06    

mais je suis obliger de faire appel a une fonction non membre , sinon je ne peut pas résoudre l'opération V = 2 * V par exemple , j'ai vu ca sur ce site :
http://www.emse.fr/~boissier/ensei [...] non-membre  
 
ça avais l'air d'être des cours donc bon ...

Reply

Marsh Posté le 27-09-2007 à 20:06:06   

Reply

Marsh Posté le 27-09-2007 à 22:51:34    

Ace17 a écrit :


Et pourquoi pas des friends?


 
parce que les operateurs binaires de type +-*/ sont symmétriques. Dans a+b, a n'a pas de rôle à jouer face à b, ca elimine d'office la fonction memebre. Reste donc fonction libre ou amie.  
La Fonction ami pete l'encapsulation alors que la fonction libre suffit a faire ce dotn tu as besoin en utilisant les accesseurs/mutateurs qui vont bien.
 
Quant à V =2*V ... faudra voir à mettre des ocnstructeurs explicites, écrire une Forme Canonique de Coplien et a pas utiliser le Bartman&Norton's Trick quand on sait pas s'en servir à bon escient.
 
Ah ouais, et pour preparer vendredi, ce cours est à chier :o
 
une version g++ compliant :
 

Code :
  1. #include <iostream>
  2. using namespace std;
  3. template <typename TYPE> class Grandeur
  4. {
  5.   public:
  6.   Grandeur(double tval=0):val(tval){};
  7.   inline double getVal() const{ return val; }
  8.   protected:
  9.   double val;
  10. };
  11. class Longueur : public Grandeur<Longueur>
  12. {
  13.   public:
  14.   Longueur(double tval=0):Grandeur<Longueur>(tval){}
  15.   Longueur(const Grandeur<Longueur>& src):Grandeur<Longueur>(src.getVal()){}
  16. };
  17. class Temps : public Grandeur<Temps>
  18. {
  19.   public:
  20.   Temps(double tval=0):Grandeur<Temps>(tval){}
  21.   Temps(const Grandeur<Temps>& src):Grandeur<Temps>(src.getVal()){}
  22. };
  23. class Vitesse : public Grandeur<Vitesse>
  24. {
  25.   public:
  26.   Vitesse(double tval=0):Grandeur<Vitesse>(tval){}
  27.   Vitesse(const Grandeur<Vitesse>& src):Grandeur<Vitesse>(src.getVal()){}
  28. };
  29. template<class T1,class T2> struct unit;
  30. template<class T> struct unit<T,T>    { typedef T type; };
  31. template<> struct unit<Temps,Vitesse> { typedef Longueur type; };
  32. template<> struct unit<Vitesse,Temps> { typedef Longueur type; };
  33. template<class T1,class T2>
  34. Grandeur< typename unit<T1,T2>::type >
  35. operator*( const Grandeur<T1>& t1, const Grandeur<T2>& t2 )
  36. {
  37.   typedef typename unit<T1,T2>::type unit_type;
  38.   typedef Grandeur<unit_type> return_type;
  39.   return return_type( t1.getVal()*t2.getVal() );
  40. }
  41. template<class T>
  42. Grandeur<T> operator*( const double& t1, const Grandeur<T>& t2 )
  43. {
  44.   typedef Grandeur<T> return_type;
  45.   return return_type( t1*t2.getVal() );
  46. }
  47. template<class T> Grandeur<T> operator*( const Grandeur<T>& t1, const double& t2 )
  48. {
  49.   typedef Grandeur<T> return_type;
  50.   return return_type( t1.getVal()*t2 );
  51. }
  52. int main()
  53. {
  54.   Longueur L(100);
  55.   Temps T (10);
  56.   Vitesse V (40);
  57.   Longueur L2 = V*T;
  58.   cout << L2.getVal() << endl;
  59.   V = V*2;
  60.   cout << V.getVal() << endl;
  61.   V = 0.5*V;
  62.   cout << V.getVal() << endl;
  63. }


 
Ensuite tu m'expliqueras comme Vitesse*Vitesse ca donne un double OU une vitesse au carré, c'est pas homogène :o

Reply

Marsh Posté le 27-09-2007 à 23:19:01    

Joel F a écrit :


parce que les operateurs binaires de type +-*/ sont symmétriques. Dans a+b, a n'a pas de rôle à jouer face à b, ca elimine d'office la fonction memebre. Reste donc fonction libre ou amie.  

Jusque-la, je suis completement d'accord avec toi.
 

Joel F a écrit :


La Fonction ami pete l'encapsulation alors que la fonction libre suffit a faire ce dotn tu as besoin en utilisant les accesseurs/mutateurs qui vont bien.

Je ne vois pas en quoi la fonction amie "pete" l'encapsulation ... peux-tu me donner un exemple ou l'emploi des fonctions amies est justifie, dans ce cas? N'existe-t-il pas des cas ou un operateur binaire doit manipuler des membres prives auquels il serait peu judicieux de donner acces, meme a travers un accesseur?  

Reply

Marsh Posté le 27-09-2007 à 23:26:45    

Ace17 a écrit :

Je ne vois pas en quoi la fonction amie "pete" l'encapsulation ... peux-tu me donner un exemple ou l'emploi des fonctions amies est justifie, dans ce cas? N'existe-t-il pas des cas ou un operateur binaire doit manipuler des membres prives auquels il serait peu judicieux de donner acces, meme a travers un accesseur?  


Je pense que c'est comme tu dis: 'des cas'. Donc à n'utiliser que lorsque l'usage y est strictement nécessaire... à mon avis.

Reply

Marsh Posté le 28-09-2007 à 00:05:39    

Franchement c'est ingénieux comme truc j'aurais jamais pensé a une implémentation comme ça, pour Vitesse*Vitesse ça devrait rendre un double mais je pense que je m'en sortirais. Je te remercie parce que j'étais vraiment bloqué

Reply

Marsh Posté le 28-09-2007 à 08:57:36    

IrmatDen a écrit :


Je pense que c'est comme tu dis: 'des cas'. Donc à n'utiliser que lorsque l'usage y est strictement nécessaire... à mon avis.


 
C'est exactement ça. Si tu peut pas faire autrement, vas y fait une fonction amie. Mais, à l'usage, tu t'apercevra que, dans 99.999999932648% des cas,
t'en a pas besoin car tu as ta pelleté d'accesseur/mutateur.
 
@titeuf789 : je comprends pas pkoi vitesse*vitesse ca devrait renvoyer un double o_O c'est physiquement incorrect.
 
@le reste :
Pour infos : http://boost.org/libs/mpl/doc/tuto [...] lysis.html
Boost::MPL fournit un exemple avec une implantation plus poussée mais utilisant le même genre d'idée.

Reply

Sujets relatifs:

Leave a Replay

Make sure you enter the(*)required information where indicate.HTML code is not allowed