Partage
  • Partager sur Facebook
  • Partager sur Twitter

Problème de surcharge d'opérateur...

Comprend pas, mais profond.

Sujet résolu
    6 avril 2008 à 14:29:21

    Bonjour,

    J'essaie de surcharger des opérateurs "+", "-" et "=" afin de faire des opérations avec des vecteurs.

    Le but recherché est celui là :

    1. #include "Vecteur3x1.h"
    2. int main() {
    3.         Vecteur3x1 A;
    4.         Vecteur3x1 B;
    5.         Vecteur3x1 C;
    6.         A.set(1,2,3);
    7.         B.set(4,5,6);
    8.         C = A + B;
    9.         C.afficher();
    10.         return 0;
    11. }



    Or, j'obtiens cette erreur à la compilation :

    D:\Dev\C++\VectVersBmp3>g++ -Wall Utils/*.cpp
    Utils/main.cpp: In function `int main()':
    Utils/main.cpp:11: error: no match for 'operator=' in 'C = (&A)->Vecteur3x1::ope
    rator+(((Vecteur3x1&)(&B)))'
    Utils/Vecteur3x1.h:23: note: candidates are: Vecteur3x1 Vecteur3x1::operator=(Ve
    cteur3x1&)



    Je n'arrive pas à comprendre cette erreur, j'aimerai penser que ce que je renvoie avec mon addition ne correspond pas à ce qu'attend l'operator=, mais dans les sources, ce n'est vraiment pas le cas... Les voilà d'ailleurs :


    1. #ifndef _VECTEUR3X1_H
    2. #define _VECTEUR3X1_H
    3.         class Vecteur3x1{
    4.                 //------ ATTRIBUTS
    5.                 public:
    6.                         double v1;
    7.                         double v2;
    8.                         double v3;
    9.                 //------ METHODES
    10.                 public:
    11.                         Vecteur3x1();
    12.                         void       set(double v1_, double v2_, double v3_);
    13.                         void       effacer();
    14.                         void       afficher();
    15.                         void       copierDepuis(Vecteur3x1& vec);
    16.                         Vecteur3x1 ajouter(Vecteur3x1& vec);
    17.                         Vecteur3x1 soustraire(Vecteur3x1& vec);
    18.                         Vecteur3x1 operator=(Vecteur3x1& vec);
    19.                         Vecteur3x1 operator+(Vecteur3x1& vec);
    20.                         Vecteur3x1 operator-(Vecteur3x1& vec);
    21.         };
    22. #endif



    1. #include <iostream>
    2. #include "Vecteur3x1.h"
    3. using namespace std;
    4. Vecteur3x1::Vecteur3x1() {
    5.         effacer();
    6. }
    7. void Vecteur3x1::set(double v1_, double v2_, double v3_) {
    8.         v1 = v1_;
    9.         v2 = v2_;
    10.         v3 = v3_;
    11. }
    12. void Vecteur3x1::effacer() {
    13.         set(0, 0, 0);
    14. }
    15. void Vecteur3x1::afficher() {
    16.         cout << "| " << v1 << " |" << endl;
    17.         cout << "| " << v2 << " |" << endl;
    18.         cout << "| " << v3 << " |" << endl;
    19. }
    20. void Vecteur3x1::copierDepuis(Vecteur3x1& vec) {
    21.         set(vec.v1, vec.v2, vec.v3);
    22. }
    23. Vecteur3x1 Vecteur3x1::ajouter(Vecteur3x1& vec) {
    24.         Vecteur3x1 vSom;
    25.         vSom.v1 = v1 + vec.v1;
    26.         vSom.v2 = v2 + vec.v2;
    27.         vSom.v3 = v3 + vec.v3;
    28.         return vSom;
    29. }
    30. Vecteur3x1 Vecteur3x1::soustraire(Vecteur3x1& vec) {
    31.         Vecteur3x1 vSou;
    32.         vSou.v1 = v1 - vec.v1;
    33.         vSou.v2 = v2 - vec.v2;
    34.         vSou.v3 = v3 - vec.v3;
    35.         return vSou;
    36. }
    37. Vecteur3x1 Vecteur3x1::operator=(Vecteur3x1& vec) {
    38.         copierDepuis(vec);
    39.         return *this;
    40. }
    41. Vecteur3x1 Vecteur3x1::operator+(Vecteur3x1& vec) {
    42.         return ajouter(vec);
    43. }
    44. Vecteur3x1 Vecteur3x1::operator-(Vecteur3x1& vec) {
    45.         return soustraire(vec);
    46. }



    Je n'arrive vraiment pas à voir d'où vient le problème... :(
    • Partager sur Facebook
    • Partager sur Twitter
      6 avril 2008 à 14:35:34

      - op=() retourne une reference, et dans ta classe il n'est pas necessaire
      - pourquoi ajouter() et soustraire() alors que op+=() et op-=() sont plus explicite
      - implemente op+() et op-() en fonction libre
      • Partager sur Facebook
      • Partager sur Twitter
        6 avril 2008 à 14:46:41

        J'ai passé op=(), op+() et op-() en libre et supprimé "ajouter()" et "soustraire()" (c'est vrai qu'on s'en tape en fait) :

        1. Vecteur3x1 Vecteur3x1::operator=(Vecteur3x1& vec) {
        2.         set(vec.v1, vec.v2, vec.v3);
        3.         return *this;
        4. }
        5. Vecteur3x1 Vecteur3x1::operator+(Vecteur3x1& vec) {
        6.         Vecteur3x1 vSom;
        7.         vSom.v1 = v1 + vec.v1;
        8.         vSom.v2 = v2 + vec.v2;
        9.         vSom.v3 = v3 + vec.v3;
        10.         return vSom;
        11. }
        12. Vecteur3x1 Vecteur3x1::operator-(Vecteur3x1& vec) {
        13.         Vecteur3x1 vSou;
        14.         vSou.v1 = v1 - vec.v1;
        15.         vSou.v2 = v2 - vec.v2;
        16.         vSou.v3 = v3 - vec.v3;
        17.         return vSou;
        18. }


        ...mais aucune différence, toujours la même erreur, et mettre le retour de op=() en void ne change rien (je renvoie un Vecteur afin de chaîner les op=(), ça m'est très utile dans mon prgramme).

        Ce cas du vecteur est essentiel, j'ai derrière une classe de Matrice3x3 basée sur le même système, avec les multiplications en plus afin de me lancer sur des transformations mathématiques d'image (rotation, translation et mise à l'echelle) de facon très simple, mais ce Vecteur est vraiment indispensable (et pas envie d'utiliser une classe toute prete, meme si mieux faite, je fais ca pour apprendre...).

        Merci de ton aide en tous cas ;)



        EDIT : je cois que je commence à comprendre, si je met (Vecteur3x1 vec) en paramètre de l'op= et non (Vecteur3x1& vec), tout baigne, donc il y a un mauvais retour de l'op+, je continue à chercher...

        EDIT2 : bon, j'arrete de chercher, l'operateur "=" fournit à la base fonctionne comme je le souhaite, pas besoin de le surcharger, mais quand même, j'aimerai comprendre pourquoi ça déconne...
        • Partager sur Facebook
        • Partager sur Twitter
          6 avril 2008 à 15:12:45

          Tu n'as pas compris ce que Chlab_lak entendait par passer les operateur + et - en fonction libres. En C++, on fait la différence entre deux grandes familles de fonctions, les fonctions membres qui sont rattachées à une classe, et les fonctions libres qui sont indépendantes. Quand Chlab_lak te dis de passer + et - sous forme de fonctions libres, il te suggère de ne plus les déclarer en tant que fonction membre de ta classe, mais en tant que fonction indépendantes.

          1. class Vecteur3x1
          2. {
          3.   // bla bla bla....
          4. };
          5. Vecteur3x1 operator+(const Vecteur3x1 & v1, const Vecteur3x1 & v2);
          6. Vecteur3x1 operator-(const Vecteur3x1 & v1, const Vecteur3x1 & v2);



          • Partager sur Facebook
          • Partager sur Twitter
          Mettre à jour le MinGW Gcc sur Code::Blocks. Du code qui n'existe pas ne contient pas de bug
            6 avril 2008 à 15:41:39

            en effet, comme int21h l'a dit, voici ce que je voulait dire (j'ai simplifié la classe et mis une indentation qui prend peu de place):
            1. class Vecteur {
            2.     public:
            3.         // ctor et autres (op=() inutile)
            4.         Vecteur &operator+=(const Vector &Other) {
            5.             myX += Other.myX;
            6.             myY += Other.myY;
            7.             myZ += Other.myZ;
            8.             return *this;
            9.         }
            10.     private:
            11.         double myX, myY, myZ;
            12. };
            13. Vecteur operator+(const Vecteur &Me, const Vecteur &Other) {
            14.     return Vecteur(Me) += Other;
            15. }
            • Partager sur Facebook
            • Partager sur Twitter
              6 avril 2008 à 15:58:09

              Merci, pendant que tu répondais, j'ai effectivement fait tout cela, étant tombé sur pas ma; de sujets de toi Chlab_lak à propos de la symétrie des opérations :

              1. .                       // ...blablabla
              2.                         Vecteur3x1& operator+=(Vecteur3x1& vec);
              3.                         Vecteur3x1& operator-=(Vecteur3x1& vec);
              4.         };
              5.         Vecteur3x1 operator+(Vecteur3x1& vec1, Vecteur3x1& vec2);
              6.         Vecteur3x1 operator-(Vecteur3x1& vec1, Vecteur3x1& vec2);
              7. #endif


              1. Vecteur3x1& Vecteur3x1::operator+=(Vecteur3x1& vec) {
              2.         v1 += vec.v1;
              3.         v2 += vec.v2;
              4.         v3 += vec.v3;
              5.         return *this;
              6. }
              7. Vecteur3x1& Vecteur3x1::operator-=(Vecteur3x1& vec) {
              8.         v1 -= vec.v1;
              9.         v2 -= vec.v2;
              10.         v3 -= vec.v3;
              11.         return *this;
              12. }
              13. //---------------------------
              14. Vecteur3x1 operator+(Vecteur3x1& vec1, Vecteur3x1& vec2) {
              15.         Vecteur3x1 vSom = vec1;
              16.         vSom += vec2;
              17.         return vSom;
              18. }
              19. Vecteur3x1 operator-(Vecteur3x1& vec1, Vecteur3x1& vec2) {
              20.         Vecteur3x1 vSou = vec1;
              21.         vSou -= vec2;
              22.         return vSou;
              23. }



              Effectivement cela amrche très bien pour faire des

              C = A + B;

              ou des

              C += A;

              Mais si j'essaie de faire :

              C += A + B;

              ...le compilo m'envoie dans les choux avec toujours le même type d'erreur que précédemment, comme s'il n'effectuait pas l'addition avant de faire l'affectation. Bien sûr, je ne m'en servirai jamais de ce type d'opération, mais j'aime à penser mes classes comme parfaitement réutilisables pour un utilisateur non averti. Est ce là la limite de la surcharge d'opérateurs ?

              Merci àvous en tous cas, j'aurai appris pas mal de concepts dans ce sujet ;)
              • Partager sur Facebook
              • Partager sur Twitter
                6 avril 2008 à 16:21:05

                1. #include <iostream>
                2. struct Vecteur {
                3.     Vecteur(void) :
                4.             X(0), Y(0), Z(0)
                5.     {}
                6.     Vecteur(double x, double y, double z) :
                7.             X(x), Y(y), Z(z)
                8.     {}
                9.     Vecteur &operator+=(const Vecteur &Other) {
                10.         X += Other.X;
                11.         Y += Other.Y;
                12.         Z += Other.Z;
                13.         return *this;
                14.     }
                15.     double X, Y, Z;
                16. };
                17. Vecteur operator+(const Vecteur &Me, const Vecteur &Other) {
                18.     return Vecteur(Me) += Other;
                19. }
                20. std::ostream &operator<<(std::ostream &Out, const Vecteur &Me) {
                21.     return Out << Me.X << ";" << Me.Y << ";" << Me.Z;
                22. }
                23. int main(void) {
                24.     Vecteur Va(10, 10, 10); // 10;10;10
                25.     Vecteur Vb = Va + Vecteur(1, 1, 1); // 11;11;11
                26.     Vecteur Vc;
                27.     Vc += Va + Vb + Vecteur(4, 4, 4); // 25;25;25
                28.     std::cout << "Va " << Va << std::endl;
                29.     std::cout << "Vb " << Vb << std::endl;
                30.     std::cout << "Vc " << Vc << std::endl;
                31.     return 0;
                32. }
                • Partager sur Facebook
                • Partager sur Twitter
                  6 avril 2008 à 16:28:30

                  Alors là, y a quand même UN truc dingue, c'est qu'en lisant ton code, je me suis dit "tiens, si j'essayais de mettre ces 'const' un peu partout finalement, ça ne peut pas faire de mal", et pan, tout marche absolument parfaitement...

                  Donc merci beaucoup pour toute la peine que tu t'es donnée !

                  Cela dit, l'erreur était peu parlante sur ce qu'il manquait...
                  • Partager sur Facebook
                  • Partager sur Twitter
                    6 avril 2008 à 16:32:31

                    ba enfaite je n'avais pas vraiment regardé ton erreur, il faut simplement prendre l'habitude d'etre le plus "const-correct" dans tes codes
                    • Partager sur Facebook
                    • Partager sur Twitter
                      6 avril 2008 à 21:52:19

                      Et surtout avec les classes manipulées par valeur que qu'un temporaire non nommé (typiquement le résultat d'une fonction, d'un calcul, etc) ne peut être accepté par une référence non constante.
                      • 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.

                      Problème de surcharge d'opérateur...

                      × 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