Thread: Weird behaviour in overloading operator+ (Xcode vs .Net)

  1. #1
    Registered User
    Join Date
    Apr 2008
    Posts
    5

    Weird behaviour in overloading operator+ (Xcode vs .Net)

    Hi there,
    I just started with programming in C++ with a video tutorial. Everything was going alright until i got to a weird compiler error while overloading the operator+ for a class I created myself (See code below).
    Since the tutorial was done in .NET and I am working with Xcode I tried the same code (copy pasted it) in .NET myself and got no compiler errors, every thing seemed fine.

    I think this is pretty strange since it's just basic C++ without having used any platform dependent code. Has anybody got any idea what it can be or how it can be solved?

    Here is the code (the error and location are after the code):

    Code:
    #include <iostream>
    
    using namespace std;
    
    //------------------------------
    //Point class begin
    //------------------------------
    class Point
    {
    public:
    	Point(float f_x = 1.0, float f_y = 1.0, float f_z = 1.0);
    	~Point();
    	
    	float getX();
    	float getY();
    	float getZ();
    	
    	void setX(float X);
    	void setY(float Y);		
    	void setZ(float Z);
    	
    	Point operator =(Point &p);
    	Point operator +(Point &p);
    	
    private:
    	float x, y, z;
    	
    protected:
    		
    };
    
    Point::Point(float f_x, float f_y, float f_z)
    {
    	x = f_x;
    	y = f_y;
    	z = f_z;
    }
    
    Point::~Point()
    {
    }
    
    float Point::getX()
    {
    	return x;
    }
    
    float Point::getY()
    {
    	return y;
    }
    
    float Point::getZ()
    {
    	return z;
    }
    
    void Point::setX(float X)
    {
    	x = X;
    }
    
    void Point::setY(float Y)
    {
    	y = Y;
    }
    
    void Point::setZ(float Z)
    {
    	z = Z;
    }
    
    Point Point::operator =(Point &p)
    {
    	setX(p.getX());
    	setY(p.getY());
    	setZ(p.getZ());
    	
    	return *this;
    }
    
    Point Point::operator +(Point &p)
    {
    	Point outP;
    	outP.setX(getX() + p.getX());
    	outP.setY(getY() + p.getY());
    	outP.setZ(getZ() + p.getZ());
    	
    	return outP;
    }
    
    //---------------------------
    //Point class end
    //---------------------------
    
    
    int main (int argc, char * const argv[]) 
    {
    	Point p1(4, 2, 1);
    	Point p2(6, 3, 8);
    	
    	Point p3;
    	p3 = p2 + p1;
    	
        return 0;
    }
    When I compile this in Xcode I get the follow error on the following line in main:
    Code:
    p3 = p2 + p1;
    error: no match for 'operator=' in 'p3 = Point::operator+(Point&)(((Point&)(& p1)))'

    as I said, if I copy paste this code to .NET (Visual C++ 2008 Express edition) it works perfectly with no errors;

    I also found out that if I write the following statement:
    Code:
    Point p3 = p2 + p1;
    the compiler doesn't give an error in Xcode and it can be run correctly with normal behaviour.

    Very strange if I may say so, but maybe it's because I'm new to C++ and I missed a detail.

  2. #2
    and the Hat of Guessing tabstop's Avatar
    Join Date
    Nov 2007
    Posts
    14,336
    In p3=p2+p1, you're using both the overloaded operator + and the overloaded operator =. The operator + returns a Point, but apparently not a modifiable lvalue that can be referenced (the operator = requires a Point&). The initializer doesn't use your overloaded operator =, but the default copy constructor.

  3. #3
    Registered User
    Join Date
    Apr 2008
    Posts
    5
    Isn't it then strange that the code does work in .Net but doesn't in Xcode, I know they both have different compiler so there will be differences but isn't this just basic C++ that should work on both platforms (mac or windows).

    Would anybody know a solution how I could make the following statement work:

    Code:
    Point p3;
    p3 = p2 + p1;

  4. #4
    The larch
    Join Date
    May 2006
    Posts
    3,573
    operator+ returns a temporary instance, which cannot be passed by non-const reference to operator=.

    It can be passed when a const reference is expected.

    So, to fix this class make it const-correct. If a method doesn't modify the instance's members, declare it const. When passing an object to a function by reference and the function is not going to modify the object (calls only const methods), pass it as a const reference.

    Code:
    class Point
    {
    public:
    	Point(float f_x = 1.0, float f_y = 1.0, float f_z = 1.0);
    	~Point();
    
    	float getX() const;
    	float getY() const;
    	float getZ() const;
    
    	void setX(float X);
    	void setY(float Y);
    	void setZ(float Z);
    
    	Point& operator =(const Point &p);
    	Point operator +(const Point &p) const;
    
    private:
    	float x, y, z;
    
    protected:
    
    };
    Actually, since your operator= does nothing but a memberwise assignment, you don't need to implement it yourself. The compiler would generate the assignment operator automatically and it would do exactly the same thing.
    Neither do you need to write the destructor, if you are not going to do anything in it.
    I might be wrong.

    Thank you, anon. You sure know how to recognize different types of trees from quite a long way away.
    Quoted more than 1000 times (I hope).

  5. #5
    Registered User
    Join Date
    Apr 2008
    Posts
    5
    Thanks for the reply, if I add the const to all the places you say it still comes up with the error. So that doesn't seem to do the trick.

    However if I remove the operator= function the error seems to disappear.
    In this case it is useless to overload the operator= function because the behavior is just normal, but what if you would want to swap x and y for example (I know it would be stupid in and = operator but just for the sake of it) or wanted to add more complex behavior and the operator= would be necessary. But because I was doing the tutorial they where showing the possibilities of overloading (that's why the destructor is there to).

    And I still think it's weird that it works in .NET but not in Xcode, anybody got any ideas about that?

    The compiler also still gives me a waring with the following note (at the line where I implement my operator=):

    note: candidates are: Point Point::operator=(Point&)

    but this seems to be exactly what I've implemented
    Last edited by Sjiep; 04-19-2008 at 09:02 AM. Reason: added warning notice

  6. #6
    and the Hat of Guessing tabstop's Avatar
    Join Date
    Nov 2007
    Posts
    14,336
    Quote Originally Posted by Sjiep View Post

    The compiler also still gives me a waring with the following note (at the line where I implement my operator=):

    note: candidates are: Point Point:perator=(Point&)

    but this seems to be exactly what I've implemented
    Of course it is: that's what it's telling you. "I know how to do operator= if you give me a Point&, but you didn't give me a Point&, so I'm stuck."

  7. #7
    Registered User
    Join Date
    Apr 2008
    Posts
    890
    Have operator= return a reference so you can chain assignments, i.e.

    Point & operator=(const Point &);

  8. #8
    Registered User
    Join Date
    Apr 2008
    Posts
    5
    Quote Originally Posted by medievalelks View Post
    Point & operator=(const Point &);
    This seems to do the trick, even tho it still gives the following warning:

    warning: reference to local variable 'outV' returned

    It does the trick and runs properly.

    Thanks everyone for the (fast) response!!

  9. #9
    C++ Witch laserlight's Avatar
    Join Date
    Oct 2003
    Location
    Singapore
    Posts
    28,413
    Eh, that's bad. It may work properly now, but returning a reference to a local variable results in undefined behaviour. Typically, operator= returns *this.

    Incidentally, I note that anon's example declaration of operator= returns a Point&, so kindly read examples carefully and ask if you are not sure why they are the way they are.
    Quote Originally Posted by Bjarne Stroustrup (2000-10-14)
    I get maybe two dozen requests for help with some sort of programming or design problem every day. Most have more sense than to send me hundreds of lines of code. If they do, I ask them to find the smallest example that exhibits the problem and send me that. Mostly, they then find the error themselves. "Finding the smallest program that demonstrates the error" is a powerful debugging tool.
    Look up a C++ Reference and learn How To Ask Questions The Smart Way

  10. #10
    Registered User
    Join Date
    Apr 2008
    Posts
    890
    Quote Originally Posted by laserlight View Post
    Eh, that's bad. It may work properly now, but returning a reference to a local variable results in undefined behaviour. Typically, operator= returns *this.
    Typically, operator= returns a *reference* to *this. Otherwise, you could not do things like this:

    std::string w, x, y, z;

    z = y = w = x = "Hello";

    This mimics the behavior of built-in types.

  11. #11
    C++ Witch laserlight's Avatar
    Join Date
    Oct 2003
    Location
    Singapore
    Posts
    28,413
    Typically, operator= returns a *reference* to *this.
    I felt that was obvious given the context, but good clarification nonetheless.

    Otherwise, you could not do things like this:
    You could also do operator chaining if operator= returns by value, but it would (semantically) result in unnecessary copies.
    Quote Originally Posted by Bjarne Stroustrup (2000-10-14)
    I get maybe two dozen requests for help with some sort of programming or design problem every day. Most have more sense than to send me hundreds of lines of code. If they do, I ask them to find the smallest example that exhibits the problem and send me that. Mostly, they then find the error themselves. "Finding the smallest program that demonstrates the error" is a powerful debugging tool.
    Look up a C++ Reference and learn How To Ask Questions The Smart Way

  12. #12
    The larch
    Join Date
    May 2006
    Posts
    3,573
    Quote Originally Posted by Sjiep View Post
    This seems to do the trick, even tho it still gives the following warning:

    warning: reference to local variable 'outV' returned

    It does the trick and runs properly.

    Thanks everyone for the (fast) response!!
    Your operator+ has an outP and has to return by value because it creates a whole new object (and operator+ should not modify either the left hand nor the right hand value).

    Operator= however should modify *this (the left hand value) and not return any local objects.

    You may need to post new code if you still have this problem.
    I might be wrong.

    Thank you, anon. You sure know how to recognize different types of trees from quite a long way away.
    Quoted more than 1000 times (I hope).

  13. #13
    Registered User
    Join Date
    Apr 2008
    Posts
    890
    Quote Originally Posted by laserlight View Post
    You could also do operator chaining if operator= returns by value, but it would (semantically) result in unnecessary copies.
    Oops. I recently argued against someone writing a "void operator=()" at work, and still had that on my brain.

  14. #14
    Registered User
    Join Date
    Apr 2008
    Posts
    5
    Well I changed the code to Anons first post but the same error still pops up:
    Code:
    #include <iostream>
    
    using namespace std;
    
    //------------------------------
    //Point class begin
    //------------------------------
    class Point
    {
    public:
    	Point(float f_x = 1.0, float f_y = 1.0, float f_z = 1.0);
    	~Point();
    	
    	float getX() const;
    	float getY() const;
    	float getZ() const;
    	
    	void setX(float X);
    	void setY(float Y);		
    	void setZ(float Z);
    	
    	Point& operator =(Point &p);
    	Point operator +(Point &p) const;
    	
    private:
    		float x, y, z;
    	
    protected:
    		
    };
    
    Point::Point(float f_x, float f_y, float f_z)
    {
    	x = f_x;
    	y = f_y;
    	z = f_z;
    }
    
    Point::~Point()
    {
    }
    
    float Point::getX() const
    {
    	return x;
    }
    
    float Point::getY() const
    {
    	return y;
    }
    
    float Point::getZ() const
    {
    	return z;
    }
    
    void Point::setX(float X)
    {
    	x = X;
    }
    
    void Point::setY(float Y)
    {
    	y = Y;
    }
    
    void Point::setZ(float Z)
    {
    	z = Z;
    }
    
    Point& Point::operator =(Point &p)
    {
    	setX(p.getX());
    	setY(p.getY());
    	setZ(p.getZ());
    	
    	return *this;
    }
    
    Point Point::operator +(Point &p) const
    {
    	Point outP;
    	outP.setX(getX() + p.getX());
    	outP.setY(getY() + p.getY());
    	outP.setZ(getZ() + p.getZ());
    	
    	return outP;
    }
    
    //---------------------------
    //Point class end
    //---------------------------
    
    
    int main (int argc, char * const argv[]) 
    {
    	Point p1(4, 2, 1);
    	Point p2(6, 3, 8);
    	
    	Point p3;
    	p3 = p2 + p1;
    	
        return 0;
    }
    The error just changed slightly because of the const:

    error: no match for 'operator=' in 'p3 = Point:perator+(Point&) const(((Point&)(& p1)))'

    Then I had a closer look at the warning it told me and come up with the following that also seems to work with no errors or warnings:

    Code:
    class Point
    {
    public:
    	Point(float f_x = 1.0, float f_y = 1.0, float f_z = 1.0);
    	~Point();
    	
    	float getX();
    	float getY();
    	float getZ();
    	
    	void setX(float X);
    	void setY(float Y);		
    	void setZ(float Z);
    	
    	Point operator =(Point *p);
    	Point operator +(Point &p);
    	
    private:
    		float x, y, z;
    	
    protected:
    		
    };
    I'm only wondering is this correct C++? It looks alright to me.

    And can anybody still tell me why my original code doesn't work in Xcode but will work in .NET?
    Last edited by Sjiep; 04-19-2008 at 11:03 PM. Reason: Added another example

  15. #15
    and the hat of sweating
    Join Date
    Aug 2007
    Location
    Toronto, ON
    Posts
    3,545
    Code:
    Point& Point::operator =(Point &p)
    should be:
    Code:
    Point& Point::operator =(const Point &p)
    because you aren't (and shouldn't be) modifying p.
    After that, it compiles fine in Comeau C++ compiler.

    Quote Originally Posted by Sjiep
    And can anybody still tell me why my original code doesn't work in Xcode but will work in .NET?
    I have no idea? Maybe one of them has a bug, or maybe one has an extension to try to make it more helpful?
    Last edited by cpjust; 04-19-2008 at 11:34 PM.

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. StretchDIBits() - weird behaviour..
    By lobo in forum Windows Programming
    Replies: 13
    Last Post: 10-04-2010, 11:23 PM
  2. VC++ 2005 Express: Weird Behaviour
    By psychopath in forum Tech Board
    Replies: 2
    Last Post: 06-21-2006, 07:47 PM
  3. Weird problem with overloading
    By Strait in forum C++ Programming
    Replies: 9
    Last Post: 02-19-2005, 07:34 AM
  4. .net
    By ygfperson in forum A Brief History of Cprogramming.com
    Replies: 18
    Last Post: 02-15-2002, 01:15 AM
  5. Visual J#
    By mfc2themax in forum A Brief History of Cprogramming.com
    Replies: 0
    Last Post: 10-08-2001, 02:41 PM