-3

I am having an error when I try to compile my code. The code is overloading operators and all of the overloaded operators have worked until I tried to assign the copy constructor. I keep getting a "MyClass operator=(const MyClass&)’ must be a nonstatic member function" error. I don't understand why overloading the "=" operator would cause such an error. Putting the "friend" special word in front of the declaration in the .h file does not fix the issue.

main.cpp

#include <iostream>
#include "Point.h"
using namespace std;


int main() {

   Point point1( 2, 5);
   Point point2 = point1;
   return 0;

}

MyClass.h

 #ifndef POINT_H_
 #define POINT_H_

 #include <iostream>
 #include <cmath>

 using namespace std;

 class Point {

  public:
    //Constructor
    Point();
    Point(const double x, const double y);

    //Copy
    Point(const Point & t);

    //Destructor
    virtual ~Point();

    //Get the x value
    double getX() const;

    //Get the y value
    double getY() const;

    //Set the x value
    void setX(double x);

    //Set the y value
    void setY(double y);

    //Return the distance between Points
    double distance(const Point& p) const;

    //Output the Point as (x, y) to an output stream
    friend ostream& operator << (ostream& out, const Point& point);

    //Comparison relationships
    friend bool operator == (const Point& lhs, const Point& rhs);
    friend bool operator < (const Point& lhs, const Point& rhs);

    //Math operators
    friend Point operator + (const Point& lhs, const Point& rhs);
    friend Point operator - (const Point& lhs, const Point& rhs);

    Point& operator = (const Point& rhs);

 private:
    double x;
    double y;
 };
 #endif /* POINT_H_ */

MyClass.cpp

 // Get the x value
 double Point::getX() const {
   return x;
 }

 // Get the y value
 double Point::getY() const {
   return y;
 }

 void Point::setX(double x) {
   this->x = x;
 }

 void Point::setY(double y) {
   this->y = y;
 }

 // Return the distance between Points
 double Point::distance(const Point& p) const{
   return abs( sqrt( pow( (x - p.getX() ), 2 ) + pow( (y - p.getY() ), 2 ) ) );
 }

 ostream& operator << (ostream& out, const Point& point){
   out << point.getX() << ", " << point.getY();
   return out;
 }

 bool operator == (const Point& lhs, const Point& rhs){
   if(lhs.x == rhs.x && lhs.y == rhs.y){ return true; }
   return false;
 }

 bool operator < (const Point& lhs, const Point& rhs){
   if(lhs.x < rhs.x && lhs.y < rhs.y){ return true; }
   return false;
 }

 Point operator + (const Point& lhs, const Point& rhs){
   Point point;
   point.x = lhs.x + rhs.x;
   point.y = lhs.y + rhs.y;

   return point;
 }

 Point operator - (const Point& lhs, const Point& rhs){
   Point point;
   point.x = lhs.x - rhs.x;
   point.y = lhs.y - rhs.y;

   return point;
 }

 Point& Point::operator = (const Point& rhs){
   x = rhs.x;
   y = rhs.y;
   return *this;
 }

 // Destructor
 Point::~Point(){}
TheWinterSnow
  • 175
  • 11

1 Answers1

2

There are a number of problems here that I'll try to break down, one by one.


With regard to your main question, because the copy assignment operator is defined inside the scope of MyClass, you also need to write its definition as being scoped inside MyClass, simply by adding MyClass:: before the function's name, as you would with any other scope. Next, you really should actually copy the data of rhs into this, and you should return a reference to *this.

MyClass& MyClass::operator=(const MyClass& rhs){
    x = rhs.x;
    y = rhs.y;
    return *this;
}

If you copy rhs into a temporary and return that, the whole semantics of copy assignment is completely broken. It'll lead to things like this:

MyClass obj1 {999.0, 2468.0};
MyClass obj2 {0.0, 0.0};
obj2 = obj1; // should copy obj1 to obj2
cout << obj2.x << " " << obj2.y << '\n'; // outputs "0.0 0.0" ??!?!?

Also be aware that this is a trivial copy constructor, you can remove it completely that the compiler will implicitly generate an identical one for you that does a member-wise copy, which in this case is completely safe. See special member functions.


In your operator+ function body, there are these lines:

MyClass myVar;
MyClass.x = lhs.x + rhs.x;
MyClass.y = lhs.y + rhs.y;
return myVar;

You probably mean myVar.x and myVar.y. MyClass only refers to a type and trying to access MyClass.x is a meaningless statement.


As a rule, you should never return a reference to a temporary object as in your current implementation. Local objects get destroyed when the function returns and this leaves you with a dangling reference to a destroyed object, whose memory will very likely be overwritten with complete garbage in the near future. Here is a good explanation of what's going on.


Let me know if you run into any further problems or if something isn't clear after reading the links. Happy coding!

alter_igel
  • 6,899
  • 3
  • 21
  • 40
  • The operator + code was incorrectly translated from my original code as I mentioned before it does work. The problem that I have now is that the = operator needs to make a new copy from one object variable to another. – TheWinterSnow Sep 30 '18 at 06:41
  • @TheWinterSnow can you explain a bit more? A copy assignment operator that doesn't assign to `this` doesn't make sense. It might help to carefully read [here](https://en.wikipedia.org/wiki/Assignment_operator_(C%2B%2B)), though the examples are a bit complicated. The first two headings should help. – alter_igel Sep 30 '18 at 06:43
  • I will update the original post with my entire source code. – TheWinterSnow Sep 30 '18 at 06:49
  • @TheWinterSnow the update doesn't help much. Is `Point` supposed to be the same as `MyClass`? Please explain what you mean by "the = operator needs to make a new copy." The copy assignment operator doesn't make any new objects, it should always leave one object logically identical to another. – alter_igel Sep 30 '18 at 06:54
  • the = operator is supossed to copy the contents of the class to another class. It should not copy the pointer or reference to the other variable. – TheWinterSnow Sep 30 '18 at 06:58
  • @TheWinterSnow you're confused about how operators and constructors work in C++. There are no pointers being used and references _cannot_ be reassigned. All that the copy assignment operator in my answer will do is copy the two `doubles` from `rhs` into `this`, by value. – alter_igel Sep 30 '18 at 07:05
  • Perhaps you're confused by `return *this;` All that does is allow you to write things like `p1 = p2 = p3;` such that all three have the same contents thereafter. It may seem quirky, but it's convention to return `*this` by reference and allow for that. You can technically also return `void` and not worry about it. The various answers to [this question](https://stackoverflow.com/questions/3105798/why-must-the-copy-assignment-operator-return-a-reference-const-reference) and [this question](https://stackoverflow.com/questions/2447696/overloading-assignment-operator-in-c) might help – alter_igel Sep 30 '18 at 07:13
  • The current code in the OP is the code that I try to compile and it will not. This is a college assignment. The assignment is to add a copy constructor and copy assignment. The example constructor is : Point(const Point & t); and the assignment is Point& operator =( const Point& rhs ); This is supposed to be in the .h file and the implementation in the .cpp file. The class is supposed to overload the = operator so that the contents of a class variable is copied into another without sharing a pointer or reference. I have just about given up. – TheWinterSnow Sep 30 '18 at 07:19
  • I'm sorry you're feeling frustrated. C++ is a difficult language that takes time. If you're horribly confused, ask your instructors for help and consider getting a [recommended C++ book for beginners](https://stackoverflow.com/questions/388242/the-definitive-c-book-guide-and-list). If it helps, I just wrote up a minimal example, just for you, that should help illustrate what's happening. You can see and run the code here: https://coliru.stacked-crooked.com/a/e090b2756cd1b317. Try and reason your through the `main` function and what it prints. – alter_igel Sep 30 '18 at 07:36
  • The final thing that I figured out and finally got the code working is that when you create an object, unlike java if you want to call the default constructor you do not use () after the variable. That is new to me 5+ semesters into computer science at community college. That little caveat messed with me – TheWinterSnow Sep 30 '18 at 07:48
  • Sounds like the "most vexing parse." It's a super annoying "quirk" in C++ which says that `Point p();` always declares a function, just because it looks like it declares a function. It doesn't create a variable `p`. It can be a pain indeed. – alter_igel Sep 30 '18 at 07:50