jalal sadeghi
jalal sadeghi

Reputation: 382

C++ operator overloading or redefine?

I want to overload + for Point+Point and Point+vector

class Vector
{
public:
    double x;
    double y;
    double z;
};

class  PointBase
{
public:

    double x;
    double y;
    double z;

        PointBase operator+(const Vector &vec) const
        {
            PointBase b;
            b.x=vec.x+this->x;
            b.y=vec.y+this->y;
            b.z=vec.z+this->z;
            return b;

        }
};

class  Point:public PointBase
{
public:
    PointBase operator+(const Point &point) const
    {
        PointBase b;
        b.x=point.x+this->x;
        b.y=point.y+this->y;
        b.z=point.z+this->z;
        return b;
    }
    Point(PointBase& base)
    {
    }
    Point()
    {
    }
};

int main()
{
    Point  p;
    Vector v;
    p=p+v;
    return 0;
}

PointBase operator+(const Point &point) const hides PointBase operator+(const Vector &vec) const, why? I expect that 2 overloads work correctly: point+vector and point +point.

Upvotes: 3

Views: 247

Answers (1)

Wintermute
Wintermute

Reputation: 44023

The operator+ in Point hides the one inherited from PointBase. To make it available, use

class  Point:public PointBase
{
public:
  using PointBase::operator+;  // <-- here

  PointBase operator+(const Point &point) const

  // rest as before

Note, however, that the next problem you'll run into is that

p=p+v

attempts to use an operator= that takes a Point on the left and a PointBase on the right and that does not exist.

The reason that the operator+ in the derived class hides the one in the base class is the way name lookup works in C++: The compiler goes outward in layers (concrete class -> base class -> base base class -> ..., and for non-member functions called from a member function continues through the surrounding namespaces1) until it finds a matching name, tries to apply it, and fails if that doesn't work. You can see the same mechanism at work in this non-compiling piece of code:

void foo(char const *) { }

namespace bar {
  void foo(int) { }

  void baz() {
    // does not compile: bar::foo hides ::foo
    foo("hello");
  }
}

In the case of your classes, the compiler looks in Point, finds a matching name, tries to apply it, and complains when it fails. It does not continue to look in the surrounding scope (PointBase), but it would continue to look if it had not found the operator+ in Point.

1 There's an asterisk for class templates that inherit other class templates here, where different mechanisms come into play. See Why do I have to access template base class members through the this pointer? for details, although none of that comes into play in your case.

Upvotes: 2

Related Questions