Thread: operator overloading

  1. #1
    GA ichijoji's Avatar
    Join Date
    Nov 2002
    Posts
    179

    operator overloading

    I have a vector class and I want to overload some operators for it, so I made the class like this:
    Code:
    class vec {
    public:
      float x, y;
      vec(float setx = 0, float sety = 0) {
        set(setx,sety);
      }
      vec(vec& rhs) {
        x = rhs.x;
        y = rhs.y;
      }
      vec operator=(vec& rhs) {
        x = rhs.x;
        y = rhs.y;
        return rhs;
      }
      vec operator+(vec& rhs) {
        vec ret(x+rhs.x,y+rhs.y);
        return ret;
      }
    };
    (with other stuff too) But when I try to compile this:
    Code:
      vec a, b, c;
      a = b + c;
    I get errors about that operator not existing like:
    7 C:\Dev-Cpp\antigrav\main.cpp no match for 'operator=' in 'a = vec::operator+(vec&)(((vec&)(&c)))'
    I was totally sure this was how to overload operators, but now I'm not so sure. What am I doing wrong?
    Last edited by ichijoji; 07-15-2005 at 03:24 PM.
    Illusion and reality become impartiality and confidence.

  2. #2
    Magically delicious LuckY's Avatar
    Join Date
    Oct 2001
    Posts
    856
    Try making the args const.

  3. #3
    Registered User
    Join Date
    Nov 2001
    Posts
    1,348
    In the overloaded assignment operator, return a constant reference.

    const vec &operator=(vec const &rhs)

    Compile and update us.

    Kuphryn

  4. #4
    Registered User
    Join Date
    Apr 2002
    Posts
    1,571
    Remove entirely your copy constructor and assignment operator. There is no need for them in this case. The default ones provided do the same thing you do.

    edit: with the exception that your assignment operator is wrong as was previously stated.
    "...the results are undefined, and we all know what "undefined" means: it means it works during development, it works during testing, and it blows up in your most important customers' faces." --Scott Meyers

  5. #5
    GA ichijoji's Avatar
    Join Date
    Nov 2002
    Posts
    179
    I ended up removing the operator=, changing the copy constructor to vec(const vec& rhs), and making the arithmetic operators independent of the class like vec operator(vec,vec) etc. The compiler seems to like this so I'm going to leave it alone on the "if it ain't broke" principle. Thanks for the help.
    Illusion and reality become impartiality and confidence.

  6. #6
    Registered User
    Join Date
    Nov 2001
    Posts
    1,348
    Well, no principle is absolute. Code is unique in that it looks right, but at times it will function incorrectly.

    Kuphryn

  7. #7
    Registered User
    Join Date
    Jun 2005
    Posts
    6,815
    Ignoring the fact that you don't need to provide operator= and copy constructors in this case, a more usual way of implementing the operators is;
    Code:
    class vec {
    public:
      float x, y;
      vec(float setx = 0, float sety = 0) {
        set(setx,sety);
      };
      vec(const vec& rhs) {
        x = rhs.x;
        y = rhs.y;
      };
      vec &operator=(const vec& rhs) {
        x = rhs.x;
        y = rhs.y;
        return *this;
      };
      vec operator+(const vec& rhs) const {
        vec ret(x+rhs.x,y+rhs.y);
        return ret;
      };
    };

  8. #8
    Just Lurking Dave_Sinkula's Avatar
    Join Date
    Oct 2002
    Posts
    5,005
    Shouldn't a constructor use "initialization lists" rather than "assignment"?

    [edit]And aren't the semicolons trailing the function definitions superfluous?
    Last edited by Dave_Sinkula; 07-15-2005 at 09:30 PM.
    7. It is easier to write an incorrect program than understand a correct one.
    40. There are two ways to write error-free programs; only the third one works.*

  9. #9
    Registered User
    Join Date
    Jun 2005
    Posts
    6,815
    Quote Originally Posted by Dave_Sinkula
    Shouldn't a constructor use "initialization lists" rather than "assignment"?
    It is often technically a requirement if some of the initialisations can throw exceptions (eg initialisation of an instance of a class). For basic types, the argument is more stylistic, particularly if one relies on an optimising compiler.

    Quote Originally Posted by Dave_Sinkula
    And aren't the semicolons trailing the function definitions superfluous?
    Technically, yes. It happens to be a stylistic preference of mine as it makes life a trifle easier if a subseqent decision is made to move the function definition out of the class declaration (which makes the semi-colons in the class declaration no longer superfluous).

  10. #10
    Just Lurking Dave_Sinkula's Avatar
    Join Date
    Oct 2002
    Posts
    5,005
    Quote Originally Posted by grumpy
    Quote Originally Posted by Dave Sinkula
    And aren't the semicolons trailing the function definitions superfluous?
    Technically, yes. It happens to be a stylistic preference of mine as it makes life a trifle easier if a subseqent decision is made to move the function definition out of the class declaration (which makes the semi-colons in the class declaration no longer superfluous).
    How so? Aren't they null statements outside of a class too?
    7. It is easier to write an incorrect program than understand a correct one.
    40. There are two ways to write error-free programs; only the third one works.*

  11. #11
    Registered User
    Join Date
    Jun 2005
    Posts
    6,815
    Quote Originally Posted by Dave_Sinkula
    How so? Aren't they null statements outside of a class too?
    My point is that moving function bodies outside class declarations makes semi-colons necessary within the class body;
    Code:
    class X
    {
       public:
        X() {}
        void SomeMethod() {}
    };
    is refactored into;
    Code:
    // class declaration in header file
    class X
    {
       public:
          X();
          void SomeMethod();
    };
    // class implementation, in another source file
    X::X()
    {
    }
    
    void X::SomeMethod()
    {
    }
    and all three semicolons in the class declaration are mandatory (or their presence or absence changes meaning of the code, depending on context).

    In practice, a fairly common way to factor out functions that are initially declared inline within a class is to cut and paste them out. And I've seen, relatively often, that people forget to add the required semicolons into the class declaration.

    Couple this with phenomenon with a large scale program, where the class declaration is in a header file, and such changes necessitate a recompile of several source (eg .cpp) files. If the program is being developed by a team, one common practice is to hold off from major rebuilds of the complete source tree as long as possible (eg overnight for moderate size programs, once a week for large programs). The progress of the whole team can be held up (meaning the team is left waiting with fingers twiddling) if such a major rebuild fails. And one way to make such a rebuild fail is to simply forget to add the semi-colons in the class declaration when refactoring.

    Ironically, the common reason for factoring code in such a way is to reduce compile times: forcing multiple source files to compile non-trivial inline functions increases compile times.

    Hence my preference for the (technically superfluous) semicolons in the class declaration.
    Last edited by grumpy; 07-17-2005 at 02:20 AM.

Popular pages Recent additions subscribe to a feed