C++ Vector Operator Overloading

21,545

There are a few things to know when you write operators, which are not as often used with other functions.

The assign operators, for example, will return *this because you change the value of the vector:

class v {
public:
  double x_, y_;
  v& operator += (const v& rhs)
  {
     _x += rhs._x;
     _y += rhs._y;
     return *this;
  }
};

Another interesting one, the pre ++ and post ++ are different only because of an unused parameter:

class v {
public:
  double x_, y_;
  v& operator ++ (); // ++v
  v& operator ++ (int); // v++
};

The "equal" (assignment) is another one that is tricky when you use pointers. For a vector, it generally won't be a problem, but if you define a vector V and assign it to itself, you have to be careful:

class v {
public:
  double x_, y_;
  v& operator = (const v& rhs)
  {
    if(this != &rhs)
    {
      x_ = rhs.x_;
      y_ = rhs.y_;
    }
    return *this;
  }
};

In your case, the if() will most certainly not be useful, but think about doing something like this:

   delete p_;
   p_ = new foo;
   p_->x_ = rhs.p_->x_;

If &rhs == this, then the delete p_ deleted the rhs pointer! That means accessing it on the 3rd line is a bug.

The rest should be easy enough to work with. The compare operators return bool and are const:

class v {
public:
  double x_, y_;
  bool operator == (const v& rhs) const
  {
    return x_ == rhs.x_ && y_ == rhs.y_;
  }
};

Although, since C++20, you are expected to only declare the three way comparison operator <=> which allows the compiler to implement all the other comparison operators for you. This one returns a negative number (smaller: a < b), 0 (equal: a == b), or a positive number (larger: a > b).

I'm not sure what makes a vector bigger or smaller, I used the length from (0, 0) in this example:

class v {
public:
  double x_, y_;
  int operator <=> (const v& rhs) const
  {
    if(x_ == rhs.x_ && y_ == rhs.y_)
    {
      return 0;
    }
    return length() > rhs.length() ? 1 : -1;
  }
};

Except for the [] operator. There are two versions of that one:

class v {
public:
  // I would imagine you'd use an array but as a simple example...
  double x_, y_;
  double operator [] (int idx) const
  {
    return idx == 0 ? x_ : y_;
  }
  v_ref operator [] (int idx)
  {
    v_ref v(this, idx);
    return v;
  }
};

As you can see, the non-constant version of the [] operator returns a reference. This is necessary so you can write something like:

r[3] = 7.3;

r[3] returns that reference, then the assignment of the reference is called with 7.3 as the parameter. (Note that we should probably throw an error if you use 3 as the index when you only have 2 values: 0 and 1--this is not shown here)

class v_ref
{
public:
  v *p_;
  int i_;
  v_ref(v *p, int i)
    : p_(p), i_(i)
  {
  }
  operator = (double q)
  {
     // again, I suppose you'd use an array instead!
     if(i_ == 0)
     {
       p_->x_ = q;
     }
     else
     {
       p_->y_ = q;
     }
  }
};

Assuming you want some security, the vector pointer could make use of a reference counter so you know whether a main vector object gets deleted before all of its reference objects...

Another note: I would imagine that your constructor will allocate an array of double (or use an std::vector<double> type...) If you use new, remember to delete in the destructor and that's when the if() in the assignment operator is very important.

Share:
21,545
SharpCode
Author by

SharpCode

Updated on August 08, 2021

Comments

  • SharpCode
    SharpCode over 2 years

    I am trying to find a simple example program that overloads the following operators of a mathematic vector.

    Constructor  // create
    
    = (equals)     // assign
    
    +; -; +=; -=   // add sub
    
    *; /; *=; /=   // multi divide
    
    ++; -- // plus minus
    
    ==    // compare
    >; >=
    <; <=
    
    []    // access a value
    

    Cant seem to find any good simple tutorials. I emphasize the simple because I am only learning this stuff now. If someone could link me or even better program a simple overload for just one of the operators as an example would be incredible!