Casey
Casey

Reputation: 10936

C++ Calling a non-const operator overload with two const arguments

I've overloaded the operator- (and -=) for 2D vectors (and scalars):

Vector2D Vector2D::operator-(const Vector2D& rhs) {
    return Vector2D(this->GetX() - rhs.GetX(), this->GetY() - rhs.GetY());
}

In order to get this call to not complain that no operator '-' matches these arguments I had to do this:

a2de::Vector2D Vector2D::GetFacingVector(const Vector2D& target, const Vector2D& source) {
    a2de::Vector2D facingVec(const_cast<Vector2D&>(target) - const_cast<Vector2D&>(source));
    return facingVec;
}

Or this:

a2de::Vector2D Vector2D::GetFacingVector(const Vector2D& target, const Vector2D& source) {
    a2de::Vector2D facingVec(Vector2D(target) - Vector2D(source));
    return facingVec;
}

Both of which seem like a very bad thing to do. (Not-with-standing the phrase "only use const_cast when you know what you're doing because the compiler will assume you do!")

Are these correct or is there a better way to accomplish the same thing?

Upvotes: 1

Views: 357

Answers (6)

emsr
emsr

Reputation: 16333

Another possibility is to make operator a nonmember function. This way you don't run into your problem. Also, both arguments could be converted to Vector2D if you have constructors to do that.

class Vector2D
{
...
    Vector2D& operator-=(const Vector2D& rhs)
    {
      this->x -= rhs.GetX();
      this->y -= rhs.GetY();
      return *this;
    }
...
};

Vector2D Vector2D::operator-(const Vector2D& lhs, const Vector2D& rhs)
{
  Vector2D temp(lhs);
  return temp -= rhs;
}

Most non-modifying arithmetic operators in the standard are non-member symmetric like this.

Upvotes: 0

Cheers and hth. - Alf
Cheers and hth. - Alf

Reputation: 145204

I'd better try to not write the words that spring to mind. Suffice it to say, they would cause extreme downvoting of this answer, and maybe even drag in the Reddit crowd. Anyways, your member function is not const, so it must be called on non-const argument.

Here's direct technical fix:

Vector2D Vector2D::operator-(const Vector2D& rhs) const
{
    return Vector2D(this->GetX() - rhs.GetX(), this->GetY() - rhs.GetY());
}

Here's a better way, with the operator as a free-standing function:

Vector2D operator-( Vector2D const& a, Vector2D const& b)
{
    return Vector2D( a.GetX() - b.GetX(), a.GetY() - b.GetY() );
}

Finally, think about naming. Do you ever write getSin( angle )? No?

Vector2D operator-( Vector2D const& a, Vector2D const& b)
{
    return Vector2D( a.x() - b.x(), a.y() - b.y() );
}

Upvotes: 1

Aesthete
Aesthete

Reputation: 18850

There are lots of ways to use const. Here are some that may fix your problem

Vector2D Vector2D::operator-(const Vector2D& rhs) const
{
    return Vector2D(this->GetX() - rhs.GetX(), this->GetY() - rhs.GetY());
}

Notice the const at the end of your method? This signifies that the method is guaranteed not to change any member variable during it's scope.

Upvotes: 2

aschepler
aschepler

Reputation: 72271

Your operator- should be declared as a const member function, meaning it promises not to change *this:

Vector2D Vector2D::operator-(const Vector2D& rhs) const {
    return Vector2D(this->GetX() - rhs.GetX(), this->GetY() - rhs.GetY());
}

Or better still, make it a non-member, so that implicit conversions can happen on both sides of a minus sign, not just the right side:

inline Vector2D operator-(const Vector2D& lhs, const Vector2D& rhs) {
    Vector2D result(lhs);
    result -= rhs;
    return result;
}

Upvotes: 2

paddy
paddy

Reputation: 63461

Your operator should be:

Vector2D Vector2D::operator-(const Vector2D& rhs) const

Note the const.

Upvotes: 2

silvesthu
silvesthu

Reputation: 399

Try mark operator- as const member function.

Upvotes: 1

Related Questions