Hello. This is my first problem post on Daniweb so feel free to overload me with info even outside the scope of this overloading problem.

I have a class Point where I have overloaded the + operator and I'm trying to overload "operator=" so that I can right something like:
Point newPos = myPos + yourPos.

g++ gives me this error (Lines 40 and 21):

In function `int main()':|
|40|error: no match for 'operator=' in 'newPos = (&myPos)->Point::operator+(((Point&)(&yourPos)))'|
|21|note: candidates are: Point Point::operator=(Point&)|
||=== Build finished: 1 errors, 0 warnings ===|

Here's my code:

#include <iostream>
using namespace std;

class Point
{
    private:
        float itsX, itsY, itsZ;
    
    public:
        Point(float x = 0.0, float y = 0.0, float z = 0.0): itsX(x), itsY(y), itsZ(z)
        {}
        float getX() const { return itsX; }
        float getY() const { return itsY; }
        float getZ() const { return itsZ; }

        Point operator +(Point &p) const
        {
            return Point(itsX + p.getX(), itsY + p.getY(), itsZ + p.getZ());
        }

        Point operator =(Point &p)
        {
            itsX = p.getX();
            itsY = p.getX();    //yes, getX uses purposely throughout for testing
            itsZ = p.getX();
            return *this;
        }
};

ostream& operator <<(ostream &stream, Point &p)
{
    stream << p.getX() << " " << p.getY() << " " << p.getZ();
    return stream;
}

int main()
{
    Point myPos(1, 2, 3), yourPos(.1, .2, .3);
    Point newPos;
    newPos = myPos + yourPos;
    cout << "myPos location:\n" << myPos << endl;
    cout << "yourPos location:\n" << yourPos << endl;
    cout << "newPos location:\n" << newPos << endl;
    return 0;
}

Strangely if i combine lines 39 - 40 as:
Point newPos = myPos + yourPos;
the default equal seems to be used and not the overloaded one and the program compiles.

And also if i change the declaration of the overload to:
Point operator =(Point p) // no longer passing a reference
the program works as i want. Although here again if i used:
Point newPos = myPos + yourPos;
A shallow copy seems to still be performed, ignoring the redefined equal.

I didn't have any problems compiling your code with VC++ Express.

There were 3 warnings about converting double to float for yourPos(.1, .2, .3) It seemed to run as expected as well.

Just a couple of other comments:

Member functions do not HAVE to use accessors, even if it is not 'this object'. This compiles and works too:

Point operator +(Point &p) const
        {
            return Point(itsX + p.itsX, itsY + p.itsY, itsZ + p.itsZ);
        }

You should make reference parameters const anytime you don't intend to modify them.

Here's a slightly modified and slightly expanded version of your code:

#include <iostream>
using namespace std;

class Point
{
    private:
        float itsX, itsY, itsZ;
    
    public:
        Point(float x = 0.0, float y = 0.0, float z = 0.0): itsX(x), itsY(y), itsZ(z)
        {}
        float getX() const { return itsX; }
        float getY() const { return itsY; }
        float getZ() const { return itsZ; }

        Point operator + (Point const & p) const
        {
            return Point(itsX + p.itsX, itsY + p.itsY, itsZ + p.itsZ);
        }

        Point & operator = (Point const & p)
        {
            itsX = p.itsX;
            itsY = p.itsX;    //yes, itsX used purposely throughout for testing
            itsZ = p.itsX;
            return *this;
        }
};

ostream & operator <<(ostream & stream, Point const & p)
{
    stream << p.getX() << " " << p.getY() << " " << p.getZ();
    return stream;
}

int main()
{
    Point myPos(1, 2, 3);
    cout << "myPos location:\n" << myPos << endl;
    Point yourPos(.1, .2, .3);
    cout << "yourPos location:\n" << yourPos << endl;
    Point newPos;
    newPos = myPos + yourPos;
    cout << "newPos location:\n" << newPos << endl;
    Point secondPos = myPos + yourPos;
    cout << "secondPos location:\n" << newPos << endl;

    cout << "direct sum:\n" << myPos + yourPos << endl;
    return 0;
}

and the output I get from it:

myPos location:
1 2 3
yourPos location:
0.1 0.2 0.3
newPos location:
1.1 1.1 1.1
secondPos location:
1.1 1.1 1.1
direct sum:
1.1 2.2 3.3

If you're still having problems with your compiler, try moving the overloaded operators out of the class so they are not implemented inline by default.

class Point
{
// -- some skipped
        Point operator + (Point const & p) const;
// -- more skipped
};

Point Point::operator + (Point const & p) const
{
    return Point(itsX + p.itsX, itsY + p.itsY, itsZ + p.itsZ);
}

Thanks Murtan. The problem cant be due to inlining since I took your modified code and suprisingly (for me) it compiled with no errors and worked as it should.

So to get my own code to work i just heeded your advice and example and passed const references to my overloaded functions and it also worked.

I would never have thought that simply changing declaration "Point operator =(Point & p)" to "Point operator =(Point const & p)" would cause this to work.

Anybody have an idea as to why g++ was complaining without the const?

BTW, i'm using code blocks under vista home.

The most common style of '+' overloading is as Herb Sutter told,

define operator +() function as a global function and, definfe operator +=() function as a member funtion is becuase you can use the '+' operator as a left or right operand.

The reason for using const modifiers is for situations like this:

Point const X(5, 2, 3);
Point Y(0, 0, 0);
Y = X;

Since x is a const, the previous version of your code will not work, but the new one will. But this isn't likely what fixed the problem with your compiler, since it would throw an exception before compiling.

The most common style of '+' overloading is as Herb Sutter told,

define operator +() function as a global function and, definfe operator +=() function as a member funtion is becuase you can use the '+' operator as a left or right operand.

This is just semantics. It doesn't matter at all. In fact, it's faster to make them all members (from a coders perspective) since you need one less argument per operator.

Some remark (to the original post).
The Point newPos = myPos + yourPos; construct is not an assignment (that's why you compile w/o errors). It's default copy constructor Point(const Point&) makes an initialization.
Free advice: if you overload an assignment operator then (as usually) you are supposed to define a copy constructor too (and vice versa). It's the other story why...

The reason for using const modifiers is for situations like this:

Point const X(5, 2, 3);
Point Y(0, 0, 0);
Y = X;

Since x is a const, the previous version of your code will not work, but the new one will.

This makes sense and seems to be a pretty important point.

Some remark (to the original post).
The Point newPos = myPos + yourPos; construct is not an assignment (that's why you compile w/o errors). It's default copy constructor Point(const Point&) makes an initialization.

From my code i agree with this point that the default copy constructor was being called. But taking a look at Murtan's example we have in main:

Point secondPos = myPos + yourPos;
cout << "secondPos location:\n" << newPos << endl;

and his output does reflect that the overloaded = is being used. So its seems in this case that the construct is working as an assignment...

Be a part of the DaniWeb community

We're a friendly, industry-focused community of developers, IT pros, digital marketers, and technology enthusiasts meeting, networking, learning, and sharing knowledge.