Ou placer un virtual operator== ?

Ou placer un virtual operator== ? - C++ - Programmation

Marsh Posté le 01-05-2004 à 16:04:31    

Bonjour,
 
Je suis novice en C++, et je suis confronté à un problème dont pour l'instant je ne connais pas la solution.
 
J'ai pour habitude de redefinir mes operator +, *, == à l'extérieur de ma classe, dans un autre fichier (operateurs.cpp par exemple) en mettant les fonctions operator en friend.
 
Mais voila, je souhaite qu'un operator== soit virtual, car je veux le redéfinir dans les sous classes. Mais il est impossible que mon friend bool operator==(...) devienne virtual, une fonction friend ne pouvant etre virtual.
 
Quelle est la solution la plus propre pour résoudre ça ?
Merci d'avance :)

Reply

Marsh Posté le 01-05-2004 à 16:04:31   

Reply

Marsh Posté le 01-05-2004 à 16:08:45    

Fait voir ta classe de base qui contient un opérateur... C'est pas clair ton histoire.
 
Tu peux ecrire ca...
 

Code :
  1. class deBase
  2. {
  3. virtual deBase operator* ( const deBase & );
  4. };
  5. class Heritee : public deBase
  6. {
  7. virtual Heritee operator* ( const Heritee & );
  8. };


Message édité par xterminhate le 01-05-2004 à 16:10:59

---------------
Cordialement, Xterm-in'Hate...
Reply

Marsh Posté le 01-05-2004 à 16:20:13    

Pour reprendre ton exemple, le probleme c'est que je définis toujours mes operateurs externes comme ca :
 

Code :
  1. class deBase
  2. {
  3. friend deBase operator* ( const deBase &, const deBase & );
  4. };


 
 
pour ensuite les définir dans un fichier à part, operateurs.cpp par exemple.
Mais il devient impossible de les rendre virtual du coup, ce qui est génant vu que je redéfini ces opérateurs dans les classes Héritées. :/
 
(hum j'ai l'impression d'avoir réécris la meme chose, donc c'est peut etre pas plus clair  [:guts] )
 
Mais bon effectivement je peux tout réécrire comme ça, mais est ce vraiment une bonne solution ? (c'est peut etre la seule ..)


Message édité par Slayne le 01-05-2004 à 16:21:05
Reply

Marsh Posté le 01-05-2004 à 16:20:38    

je pense pas que ça soit très sain de faire des opérateurs virtuels, encore moins les binaires

Reply

Marsh Posté le 01-05-2004 à 16:22:43    

Désolé, mais je ne comprends pas ce que tu veux faire. Rendre virtuel des opérateurs n'est pas une finalité e nsoi. As tu vraiment les idées claires en terme de programmation objet ?


---------------
Cordialement, Xterm-in'Hate...
Reply

Marsh Posté le 01-05-2004 à 16:34:22    

Bon d'accord je prend un exemple qui j'espere sera plus clair.
 
Comme classe mère, je prend une classe abstraite Forme.

Code :
  1. class Forme
  2. {
  3. public :
  4. friend operator==(const Forme &,const Form & );
  5. protected :
  6. Point centre;
  7. }


 
Son operator== retournera true si le centre des 2 Formes est le meme.
 
Les classes qui hériteront de Forme seront Carré,Cercle, Triangle, etc.
Par exemple Cercle :
 

Code :
  1. class Cercle : public Forme
  2. {
  3. public :
  4. friend bool operator==(const Carre &,const Carre & );
  5. private :
  6. double rayon;
  7. }


 
Si je fais un :
Cercle c1(Point(0,0),2);
Cercle c2(Point(0,0),3);
c1 == c2;
Il n'y aura aucun soucis, ca retournera false, les 2 cercles n'ont pas le meme rayon.
 
en revanche, un :
Forme *c3 = new Cercle(c1);
Forme *c4 = new Cercle(c2);
(*c3) == (*c4);
Ca retournera vrai vu que ce sera operator== de Forme qui sera appelé.
 
J'espere avoir été plus clair cette fois ci  :)


Message édité par Slayne le 01-05-2004 à 16:35:31
Reply

Marsh Posté le 01-05-2004 à 16:37:40    

les friend cai mal

Reply

Marsh Posté le 01-05-2004 à 16:39:03    

Code :
  1. #include <iostream>
  2. struct Base
  3. {
  4.   virtual ~Base()
  5.   { }
  6.   virtual bool less(const Base &other) const =0;
  7. };
  8. struct Foo
  9.   : public Base
  10. {
  11.   bool less(const Foo &other) const
  12.   {
  13.     std::cout << "bool Foo::less(const Foo &other) const\n";
  14.     return this < &other;
  15.   }
  16.   virtual bool less(const Base &other) const
  17.   {
  18.     std::cout << "bool Foo::less(const Base &other) const\n";
  19.     return less(dynamic_cast<const Foo &>(other));
  20.   }
  21. };
  22. struct Bar
  23.   : public Base
  24. {
  25.   bool less(const Bar &other) const
  26.   {
  27.     std::cout << "bool Bar::less(const Bar &other) const\n";
  28.     return this < &other;
  29.   }
  30.   virtual bool less(const Base &other) const
  31.   {
  32.     std::cout << "bool Bar::less(const Base &other) const\n";
  33.     return less(dynamic_cast<const Bar &>(other));
  34.   }
  35. };
  36. inline bool operator<(const Base &lhs, const Base &rhs)
  37. {
  38.   std::cout << "bool operator<(const Base &lhs, const Base &rhs)\n";
  39.   return lhs.less(rhs);
  40. }
  41. inline bool operator<(const Foo &lhs, const Foo &rhs)
  42. {
  43.   std::cout << "bool operator<(const Foo &lhs, const Foo &rhs)\n";
  44.   return lhs.less(rhs);
  45. }
  46. inline bool operator<(const Bar &lhs, const Bar &rhs)
  47. {
  48.   std::cout << "bool operator<(const Bar &lhs, const Bar &rhs)\n";
  49.   return lhs.less(rhs);
  50. }
  51. int main()
  52. {
  53.   Base *b1, *b2;
  54.   Foo f1, f2;
  55.   Bar g1, g2;
  56.   std::cout << "Foo < Foo\n";
  57.   f1 < f2;
  58.   std::cout << '\n';
  59.   std::cout << "Bar < Bar\n";
  60.   g1 < g2;
  61.   std::cout << '\n';
  62.   b1 = &f1;
  63.   b2 = &f2;
  64.   std::cout << "Base& < Base& -> Foo < Foo\n";
  65.   *b1 < *b2;
  66.   std::cout << '\n';
  67.   b1 = &g1;
  68.   b2 = &g2;
  69.   std::cout << "Base& < Base& -> Bar < Bar\n";
  70.   *b1 < *b2;
  71.   std::cout << '\n';
  72.  
  73.   b1 = &f1;
  74.   b2 = &g1;
  75.   try
  76.     {
  77.       std::cout << "Base& < Base& -> Foo < Bar\n";
  78.       *b1 < *b2;
  79.     }
  80.   catch(std::bad_cast &ex)
  81.     {
  82.       std::cout.flush();
  83.       std::cerr << "Failed " << ex.what() << '\n';
  84.     }
  85. }

Reply

Marsh Posté le 01-05-2004 à 16:43:31    

Si tes operateurs prennent en argument des objets de la classe dans laquelle ils sont définis, je vois pas l'interet de friend.
 

Code :
  1. class Forme
  2. {
  3. public :
  4. virtual bool operator== ( const Forme & ) = 0;
  5. };
  6. class Cercle : public Forme
  7. {
  8. public :
  9. virtual bool operator== ( const Forme & );
  10. };
  11. class Carre : public Forme
  12. {
  13. public :
  14. virtual bool operator== ( const Forme & );
  15. };


Message édité par xterminhate le 01-05-2004 à 17:15:24

---------------
Cordialement, Xterm-in'Hate...
Reply

Marsh Posté le 01-05-2004 à 16:48:37    

xterminate > sauf que toi tu n'a absolument rien compris à rien ... alors avant de conseiller ...

Reply

Marsh Posté le 01-05-2004 à 16:48:37   

Reply

Marsh Posté le 01-05-2004 à 16:49:10    

Quel est le problème, j'essais de comprendre en effet ?


---------------
Cordialement, Xterm-in'Hate...
Reply

Marsh Posté le 01-05-2004 à 16:50:24    

--Message édité par xterminhate le 01-05-2004 à 16:48:45--

Reply

Marsh Posté le 01-05-2004 à 16:51:35    

toute façon essaie avec ta méthode, ça ne peut pas marcher ...

Reply

Marsh Posté le 01-05-2004 à 16:57:47    

Forme *c3 = new Cercle(c1);  
Forme *c4 = new Cercle(c2);  
(*c3) == (*c4);
 
C'est bien le == de Forme qui est appelé... et apres ? C'est quoi l'objectif ?


---------------
Cordialement, Xterm-in'Hate...
Reply

Marsh Posté le 01-05-2004 à 17:03:07    

xtermin : Mes operateurs prennent des objets de ma classe c'est vrai, mais ils n'influent absolument pas sur elle. Ce ne sont pas des méthodes de classes, et en général je les mets justement à l'extérieur de mon fichier maclasse.cpp.
 
Taz : Ta solution peut etre pas mal en effet. Enfin du moins le résultat c'est ce que je veux. Mais il risque d'y avoir une duplication de code dans mon cas, vu que ce serait plutot à la classe mère de comparer ses paramètres, et pas à ses classes filles.
Tu vois ce que je veux dire ?  

Reply

Marsh Posté le 01-05-2004 à 17:03:49    

xterminhate a écrit :

Forme *c3 = new Cercle(c1);  
Forme *c4 = new Cercle(c2);  
(*c3) == (*c4);
 
C'est bien le == de Forme qui est appelé... et apres ? C'est quoi l'objectif ?


 
Mon objectif, c'est que ce soit le == de Cercle qui soit appelé dans ce cas précis.

Reply

Marsh Posté le 01-05-2004 à 17:14:51    

Slayne a écrit :


Taz : Ta solution peut etre pas mal en effet. Enfin du moins le résultat c'est ce que je veux. Mais il risque d'y avoir une duplication de code dans mon cas, vu que ce serait plutot à la classe mère de comparer ses paramètres, et pas à ses classes filles.
Tu vois ce que je veux dire ?

non. ça veut rien dire ce que tu dis : si tu as une hiérarchie, chaque classe doit être capable de faire une comparaison entre 2 de ses instances. on a jamais vu quelqu'un rajouter du code à dans sa classe mère à chaque fois qu'on ajouter une classe fille.
 
(qui corresponds à mon bool less(const Class& ) const pour Bar et Foo). on map ces less sur des bool operator<(const Classe&, const Classe& ). là quand on manipule 2 instances de même type (statiquement) on a le comportement classique sans surcout.
 
après on a pas de multimethodes, alors on se débrouille pour rajouter quelque chose sans surcout pour le cas normal: chaque classe dérivant de Base doit fournir un bool less(const Base& ) const.
 
y a un peu de duplication mais pas tant que ça, puisqu'on écrit operator<(const Base&, const Base& ) une fois pour toute, la liaison virtuelle assurant l'appel correct et le cast de la seconde opérande

Reply

Marsh Posté le 01-05-2004 à 17:17:43    

Ah je commence à comprendre, mais auras tu le cas suivant :
 

Code :
  1. Carre Car;
  2. Cercle Cer;
  3. Forme *F1,*F2;
  4. F1 = Car;
  5. F2 = &Cer;
  6. *F1 == *F2; // comparaison entre deux objets de classes différentes ?


Message édité par xterminhate le 01-05-2004 à 17:20:43

---------------
Cordialement, Xterm-in'Hate...
Reply

Marsh Posté le 01-05-2004 à 17:25:14    

qui n'a aucun sens. essaie mon programme. quand on compare un Foo et un Bar dynamiquement, une exception est lancée

Reply

Marsh Posté le 01-05-2004 à 17:27:08    

Forme est abstraite, tu ne peux pas l'instancier xterm, juste utiliser des pointeurs vers des Formes.
En revanche oui je veux pouvoir comparer 2 formes différentes ... ce qui me retournera false.
 
Taz : Tu n'as pas du comprendre ce dont je parlais. Je ne veux pas toucher à la classe mère, je veux juste que la classe mère teste ces propres champs.
 
Par exemple, voila la meilleur solution que j'ai trouvé pour l'instant :  

Code :
  1. class Forme
  2. {
  3. private :
  4. Point centre;
  5. protected :
  6. virtual bool operator==(const Forme &f){
  7.   return this->centre == f.centre;
  8. }
  9. }
  10. class Cercle
  11. : public Forme
  12. {
  13. private :
  14. double rayon;
  15. public :
  16. bool operator==(const Forme &f){
  17.   if (typeid(*this) == typeid(f))
  18.   {
  19.     return this->Forme::operator==(f) && this->rayon == f.rayon;
  20.   }
  21. return false;
  22. }
  23. }


 
Ca ferait ce que je veux, sans duplication, mais ca a le defaut de transformer mon operator== en methode de classe.
Si tu trouves que c'est moche, dis le moi  :D


Message édité par Slayne le 01-05-2004 à 17:29:46
Reply

Marsh Posté le 01-05-2004 à 17:31:46    

cai toi qui a rien compris : ton code est complètement pourri d'une part (ne jamais utilisé typeid quand on ne sait pas ce que c'est)
 
après t'as rien compris : rien ne t'empêche de rendre non-virtuelle ma Base::less et de faire en sorte que chaque Classe::less(const Class& ) const fasse appel à Base::less(const Base & ) const

Reply

Marsh Posté le 01-05-2004 à 17:33:09    

toute façon tout ça est un peu tendancieux, confier aux opérateur a X b de faire les conversions ... je pense qu'il vaut mieux essayer d'éviter et de s'assurer soit même par cast de ce que sont les objets avec de leur appliquer des opérations typées et symétriques

Reply

Marsh Posté le 01-05-2004 à 17:37:31    

Ce n'est pas compliqué : il ne faut pas avoir à comparer deux objets de type différents ! C'etait l'une de mes premières remarques au sujet de la conception de ton programme....


Message édité par xterminhate le 01-05-2004 à 17:37:49

---------------
Cordialement, Xterm-in'Hate...
Reply

Marsh Posté le 01-05-2004 à 17:38:51    

Ou alors, il faut que == soit défini dans Forme et compare des attributs qui sont communs à toutes les formes hérités (genre : surface, nb de sommets, ...etc).


Message édité par xterminhate le 01-05-2004 à 17:39:25

---------------
Cordialement, Xterm-in'Hate...
Reply

Marsh Posté le 01-05-2004 à 17:44:36    

Taz a écrit :

cai toi qui a rien compris : ton code est complètement pourri d'une part (ne jamais utilisé typeid quand on ne sait pas ce que c'est)
Supair  [:meganne]  
 
après t'as rien compris : rien ne t'empêche de rendre non-virtuelle ma Base::less et de faire en sorte que chaque Classe::less(const Class& ) const fasse appel à Base::less(const Base & ) const
Ca revient a faire ce que j'ai fait quoi sauf pour Base


 
Et le castage est impossible si je veux créer une liste de Forme par exemple. Quand je voudrais en supprimer une, il faudra bien que je compare 2 formes différentes entre elles  :o  
Merci quand meme de ta participation mais si c'est pour dire des conneries ou insulter tu peux laisser ta place merci  :hello:

Reply

Marsh Posté le 01-05-2004 à 17:45:09    

xterminhate a écrit :

Ou alors, il faut que == soit défini dans Forme et compare des attributs qui sont communs à toutes les formes hérités (genre : surface, nb de sommets, ...etc).


 
C'est ça  :)

Reply

Marsh Posté le 01-05-2004 à 17:46:34    

Ben alors tu n'as pas besoin de tout ce qui s'est écrit ici bas. Tu fais juste == non virtual, non friend, dans Forme et terminé.


---------------
Cordialement, Xterm-in'Hate...
Reply

Marsh Posté le 01-05-2004 à 17:49:58    

Déclares les attributs communs dans Forme et mets les à jour depuis des classes dérivées....


Message édité par xterminhate le 01-05-2004 à 17:50:12

---------------
Cordialement, Xterm-in'Hate...
Reply

Marsh Posté le 01-05-2004 à 17:51:31    

xterminhate a écrit :

Ben alors tu n'as pas besoin de tout ce qui s'est écrit ici bas. Tu fais juste == non virtual, non friend, dans Forme et terminé.


 
Ca marchera pour comparer les attributs communs aux 2 formes c'est vrai, mais pas pour comparer les spécifités de chaque forme.
Le == de forme teste si le centre de chaque forme est le meme, le == de cercle appelera celui de forme et testera ces propres attributs (son rayon).

Reply

Marsh Posté le 01-05-2004 à 17:54:45    

Un truc comme ca, te conviendrait il ?
 
1) comparer les attributs communs des deux objets
2) comparer le type des deux objets
3') si les types sont identiques alors comparer les attributs spécifiques.
3" ) si les types sont différents, ... rien.


---------------
Cordialement, Xterm-in'Hate...
Reply

Marsh Posté le 01-05-2004 à 17:56:24    

Pour comparer le type de deux objets c'est pas compliqué en le faisant soit même.
 
Tu déclares un fonctions : virtual std::string type() = 0; dans Forme et par exemple : virtual std::string type() { reutrn "Cercle"; } dans la classe cercle, etc...


---------------
Cordialement, Xterm-in'Hate...
Reply

Marsh Posté le 01-05-2004 à 17:57:07    

et tu fais un truc tout bete : objet1.type() == objet2.type()...


---------------
Cordialement, Xterm-in'Hate...
Reply

Marsh Posté le 01-05-2004 à 17:59:37    

non. à partir du moment ou les types diffèrent, il faut lancer une erreur. donc  
 
si même type
  - comparer
sinon
  - lancer exception
 
 
je comprends pas vos histoires, si Cercle décide que operator==(Cercle, Cercle) reposent sur operator==(Forme, Forme) il doit pouvour le faire, et si carré décide que son operator)== n'a besoin de rien d'autre, il faut le laisser faire aussi

Reply

Marsh Posté le 01-05-2004 à 17:59:55    

xterminhate a écrit :

et tu fais un truc tout bete : objet1.type() == objet2.type()...

jamais
 
edit: non mais tu le fais exprès ou t'as vraiment rien compris à rien ?


Message édité par Taz le 01-05-2004 à 18:00:24
Reply

Marsh Posté le 01-05-2004 à 18:01:33    

qu'est ce que ca gène ?


---------------
Cordialement, Xterm-in'Hate...
Reply

Marsh Posté le 01-05-2004 à 18:03:19    

que tu ne t'y connais absolument pas, que tu conseilles tout et n'importe quoi, tu ferais mieux d'apprendre un peu avant d'être de mauvais conseil

Reply

Marsh Posté le 01-05-2004 à 18:04:01    

C'est facile de dire ca :) Je m'enerve pas au moins !


---------------
Cordialement, Xterm-in'Hate...
Reply

Marsh Posté le 01-05-2004 à 18:05:33    

ben c'est pas sympa de conseiller des choses entre débutants quand on y connait rien ...

Reply

Marsh Posté le 01-05-2004 à 18:06:33    

Pas de problèmes :)


---------------
Cordialement, Xterm-in'Hate...
Reply

Marsh Posté le 01-05-2004 à 18:08:57    


 
Pourquoi pas ?


---------------
Cordialement, Xterm-in'Hate...
Reply

Marsh Posté le    

Reply

Sujets relatifs:

Leave a Replay

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