CodeGuru Home VC++ / MFC / C++ .NET / C# Visual Basic VB Forums Developer.com
Results 1 to 15 of 15
  1. #1
    Join Date
    Jan 2009
    Posts
    56

    Operator Overloading, in General

    I'm having trouble overriding the + and - operators.


    My struct definition with overloaded methods:
    Code:
    struct vectorf
    {
    	float x;
    	float y;
    	float z;
    
    	const vectorf operator+(const vectorf other);
    	const vectorf operator-(const vectorf other);
    };
    
    const vectorf vectorf::operator+(vectorf other)
    {
    	vectorf ans;
    
    	ans.x = x + other.x;
    	ans.y = y + other.y;
    	ans.z = z + other.z;
    
    	return ans;
    }
    
    const vectorf vectorf::operator-(const vectorf other)
    {
    	vectorf ans;
    
    	ans.x = x - other.x;
    	ans.y = y - other.y;
    	ans.z = z - other.z;
    
    	return ans;
    }


    And this is the line of code giving me trouble:
    Code:
    glTranslateVector(MAIN_POSITION - BACKGROUND_POSITION);


    The error says:
    " error C2678: binary '-' : no operator found which takes a left-hand operand of type 'const vectorf' (or there is no acceptable conversion) "

    And:
    " could be 'const vectorf vectorf:: operator -(const vectorf)' "


    Any help would be greatly appreciated.
    -Salbris
    Last edited by Salbrismind; April 29th, 2009 at 05:01 PM. Reason: Removing unnessary sentence

  2. #2
    Join Date
    Jan 2006
    Location
    Singapore
    Posts
    6,765

    Re: Operator Overloading, in General

    Member operator+ and operator- should be defined as const member functions. You may want to define member operator+= and operator-= instead and then implement non-member operator+ and operator- respectively using those member functions.

    By the way, pass by const reference.
    C + C++ Compiler: MinGW port of GCC
    Build + Version Control System: SCons + Bazaar

    Look up a C/C++ Reference and learn How To Ask Questions The Smart Way
    Kindly rate my posts if you found them useful

  3. #3
    Join Date
    Jan 2009
    Posts
    56

    Re: Operator Overloading, in General

    Quote Originally Posted by laserlight View Post
    Member operator+ and operator- should be defined as const member functions. You may want to define member operator+= and operator-= instead and then implement non-member operator+ and operator- respectively using those member functions.

    By the way, pass by const reference.
    I know a bit, but I don't understand all of what you say:

    1) How do I define operator+ and operator- as const member functions. What does that mean?

    2) How would I go about do what you said in the second sentence?

    3) Const reference? You mean like a pointer to the struct?


    Sorry if I'm asking a bit much. Still learning myself.

    -Thanks

  4. #4
    Join Date
    Apr 2009
    Location
    Netherlands
    Posts
    91

    Re: Operator Overloading, in General

    Quote Originally Posted by Salbrismind View Post
    I know a bit, but I don't understand all of what you say:

    1) How do I define operator+ and operator- as const member functions. What does that mean?

    2) How would I go about do what you said in the second sentence?

    3) Const reference? You mean like a pointer to the struct?


    Sorry if I'm asking a bit much. Still learning myself.

    -Thanks
    1:

    It means it is a read only function and doesn't modify the object its called on. (http://msdn.microsoft.com/en-us/library/6ke686zh.aspx). This sort of enforcing of rules on your program may not make sense at first, but you'll be happy you did it when you code base gets large and you start forgetting the original intent of a function, or accidently put in some functionality that is unintendedly trying to modify the object you are calling it on. If other people use your code, they'll thank you for it to.

    2:
    Not sure I'm not that proficient on operator overloading.

    3:
    Are you a C programmer? You should probably know about references (&) in c++. They are like a pointer in the sense that they are a memory address, except they always point to the same object. passing by reference gives a performance gain because it doesn't copy the object, but simply passes its address in memory so you can access the orginial object. const tells you that the parameters will not be modified in the function. This gives the security of pass by value but the speed of pass by reference.
    Last edited by AlastrionaAdair; April 29th, 2009 at 06:22 PM.

  5. #5
    Join Date
    Jan 2008
    Location
    California, USA
    Posts
    822

    Re: Operator Overloading, in General

    Quote Originally Posted by Salbrismind View Post

    2) How would I go about do what you said in the second sentence?
    Hello Salbrismind
    I am by no means an expert, but this might help.
    Code:
    #include <iostream>
    #include <string>
    
    using namespace std;
    
    class Foo
    {
        public:
        Foo():
            bar("Bar "),
            barOne("BarOne "),
            barTwo("BarTwo ")
            {} // default ctor
    
        Foo& operator+=(const Foo& rhs)
        {
            // Here, we need to apply += to every data members
            bar += rhs.bar;
            barOne += rhs.barOne;
            barTwo += rhs.barTwo;
            return *this;
        }
    
        // test
        void say() const
        {
            cout << bar << barOne << barTwo << endl;
        }
    
        private:
        string bar, barOne, barTwo; // and so on with others
    };
    
    // nonmember non-friend
    const Foo operator+(const Foo& lhs, const Foo& rhs)
    {
        // Possibly RVO
        // Plus, we need to main tain only one statement
        return Foo(lhs) += rhs;
    }
    
    int main()
    {
        Foo a, b;
        Foo c = a+ b;
        c.say();
    }
    It is my understanding that the temporary object from the return statement
    could be eliminated, and is what commonly refered to as Return Value Optimization.
    The reason we prefer to implment operator+ in terms of operator+= is (or their counterparts)
    because it helps to improve code maintanence and allows us to utilize RVO (as shown above)
    We can further improve it by something similar to
    http://en.wikibooks.org/wiki/More_C&#37;.../Copy-and-swap
    There was a good discussion about this a while back which helped me to learn.
    Hope it does the same for you.

    Bye~

    Edit: Fixed some error!
    Last edited by potatoCode; April 29th, 2009 at 08:19 PM.

  6. #6
    Join Date
    Jan 2009
    Posts
    56

    Re: Operator Overloading, in General

    AlastrionaAdair:

    Thanks, that was very helpful. Although since I'm using the += operator now I cannot make the function const. But I'll try to remember that for later.

    Somehow I didn't realize what I was saying until now. I understand constant reference, I just forgot that structs in c++ can be referenced. I'm more experienced in C than C++ or C#.



    potatoCode:

    You helped fix my issues, thank you very much!



    Problem solved.

  7. #7
    Join Date
    Jul 2002
    Location
    Portsmouth. United Kingdom
    Posts
    2,727

    Re: Operator Overloading, in General

    I can never remember all of the member/non-member, return reference/value etc rules.
    I have them all written down on a sheet of paper pinned above my desk.
    "It doesn't matter how beautiful your theory is, it doesn't matter how smart you are. If it doesn't agree with experiment, it's wrong."
    Richard P. Feynman

  8. #8
    Join Date
    Apr 2009
    Location
    Netherlands
    Posts
    91

    Re: Operator Overloading, in General

    Quote Originally Posted by JohnW@Wessex View Post
    I can never remember all of the member/non-member, return reference/value etc rules.
    I have them all written down on a sheet of paper pinned above my desk.
    Personally I don't think its that hard to rmember, simply never give more access/functionality then is needed. If you don't need a pointer use a reference, if its a small data type simply pass by value. For const my rule is that you only need to give the most minimal access rights.

    For me its mainly hard to remain consitent because you have to keep thinking about what you're doing, at least until it becomes second nature. I tend to get carried away in what I'm doing and simply ignore all the rules to get a certain functionality working. Then I have to go back and check all the stuff and enforce the rules :P.

  9. #9
    Join Date
    Jul 2002
    Location
    Portsmouth. United Kingdom
    Posts
    2,727

    Re: Operator Overloading, in General

    I meant the rules for operator overloading.

    i.e.

    pre-increment
    Return a reference to *this.

    post-increment
    Return by value and make the function const.

    operator +
    Friend function, defined in terms of +=, return by value.

    etc.
    "It doesn't matter how beautiful your theory is, it doesn't matter how smart you are. If it doesn't agree with experiment, it's wrong."
    Richard P. Feynman

  10. #10
    Join Date
    Jan 2006
    Location
    Singapore
    Posts
    6,765

    Re: Operator Overloading, in General

    Quote Originally Posted by JohnW@Wessex
    post-increment
    Return by value and make the function const.
    hmm... but isn't it wrong to make the function const? After all, it should still be modifying the current object. Yet, whether to make a member function const or non-const is more than just about operator overloading when the operator is defined as a member function; it is about member functions in general.

    Quote Originally Posted by JohnW@Wessex
    operator +
    Friend function, defined in terms of +=, return by value.
    Same goes for this, methinks. Like, if you are able to implement the function using the public interface of the class, then you know that it should be a non-member non-friend function. Consequently, you can reason that if operator+ is defined in terms of +=, it need not be a friend function. So, what you might need to remember is to consider whether you should define operator+ in terms of operator+= and whether it should return by value or by reference... but the latter should become obvious when you are actually trying to implement it, right?
    C + C++ Compiler: MinGW port of GCC
    Build + Version Control System: SCons + Bazaar

    Look up a C/C++ Reference and learn How To Ask Questions The Smart Way
    Kindly rate my posts if you found them useful

  11. #11
    Join Date
    Jul 2002
    Location
    Portsmouth. United Kingdom
    Posts
    2,727

    Re: Operator Overloading, in General

    Quote Originally Posted by laserlight View Post
    hmm... but isn't it wrong to make the function const?
    Sorry, got that wrong. I meant const return.

    So, what you might need to remember is to consider whether you should define operator+ in terms of operator+= and whether it should return by value or by reference... but the latter should become obvious when you are actually trying to implement it, right?
    Your memory is obviously better than mine. When I get to that point I'm thinking "Return by value or reference. Const?" The problem is if you remember it incorrectly then everything may appear to work... for a while. I'm sure the rules will stick eventually, but for now I'm keeping my crib sheet.
    "It doesn't matter how beautiful your theory is, it doesn't matter how smart you are. If it doesn't agree with experiment, it's wrong."
    Richard P. Feynman

  12. #12
    Join Date
    Jul 2002
    Location
    Portsmouth. United Kingdom
    Posts
    2,727

    Re: Operator Overloading, in General

    For example, the const return is an easy one to forget.

    Code:
    class Test1
    {
    public:
        Test1(int v) : value(v)
        {
        }
    
        Test1 operator ++ (int)
        {
            Test1 temp(*this);
    
            ++value;
    
            return temp;
        }
    
    private:
        int value;
    };
    
    class Test2
    {
    public:
        Test2(int v) : value(v)
        {
        }
    
        const Test2 operator ++ (int)
        {
            Test2 temp(*this);
    
            ++value;
    
            return temp;
        }
    
    private:
        int value;
    };
    
    
    int main()
    {
        Test1 t1(0);
    
        (t1++)++;   // This compiles, but would be illegal for a POD type.
    
        Test2 t2(0);
    
        (t2++)++;  // Compiler error.
    }
    "It doesn't matter how beautiful your theory is, it doesn't matter how smart you are. If it doesn't agree with experiment, it's wrong."
    Richard P. Feynman

  13. #13
    Join Date
    Jan 2006
    Location
    Singapore
    Posts
    6,765

    Re: Operator Overloading, in General

    Quote Originally Posted by JohnW@Wessex
    For example, the const return is an easy one to forget.
    But it also matters little in this context. In fact, Sutter and Alexandrescu point out in C++ Coding Standards that returning by const value, while stopping the use of undesired syntax, sometimes also stops the use of elegant syntax. In the case of the post-increment operator both undesired syntax and elegant syntax seem like remote concerns to me, but in the example cited, where operator+ was used in conjunction with code that modified the temporary, the elegant code makes sense.
    C + C++ Compiler: MinGW port of GCC
    Build + Version Control System: SCons + Bazaar

    Look up a C/C++ Reference and learn How To Ask Questions The Smart Way
    Kindly rate my posts if you found them useful

  14. #14
    Join Date
    Jul 2002
    Location
    Portsmouth. United Kingdom
    Posts
    2,727

    Re: Operator Overloading, in General

    The point in my example was that the result is neither undesired syntax or even elegant syntax.
    It just doesn't do what it first appears to do.
    Code:
    (t1++)++; // Increment t1 by one!
    The actual code may not be as obvious as this, causing strange and hard to find bugs.
    I prefer to stick with the philosophy of 'least surprise' and make operators work as much as possible to POD rules.
    Last edited by JohnW@Wessex; May 1st, 2009 at 03:08 AM.
    "It doesn't matter how beautiful your theory is, it doesn't matter how smart you are. If it doesn't agree with experiment, it's wrong."
    Richard P. Feynman

  15. #15
    Join Date
    Jan 2006
    Location
    Singapore
    Posts
    6,765

    Re: Operator Overloading, in General

    Quote Originally Posted by JohnW@Wessex
    The point in my example was that the result is neither undesired syntax or even elegant syntax.
    It just doesn't do what it first appears to do.
    Therefore it is undesired syntax.

    Quote Originally Posted by JohnW@Wessex
    The actual code may not be as obvious as this, causing strange and hard to find bugs.
    I prefer to stick with the philosophy of 'least surprise' and make operators work as much as possible to POD rules.
    Ah, but in that case, you should be applying this rule as a general rule, not just one for operators. That is, when you want to return by value, return by const value. So, it is not so much about making "operators work as much as possible to POD rules", but about trying to design an interface that is hard to misuse.

    The trade-off is that you then get an interface that might be slightly less flexible, but that is the same whether it is applied to operators or named functions. My preference would be to allow the flexibility, not only because it is in line with what the standard library already does, but also because I see the possible misuse as unlikely.
    C + C++ Compiler: MinGW port of GCC
    Build + Version Control System: SCons + Bazaar

    Look up a C/C++ Reference and learn How To Ask Questions The Smart Way
    Kindly rate my posts if you found them useful

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •  





Click Here to Expand Forum to Full Width

Featured