Pure virtual operator

Casandra picture Casandra · May 22, 2013 · Viewed 7k times · Source

I have a project for school in C++ and I am stuck on one part: I have to overload the operators + and * to work with geometrical figures. That was no problem, but here it where it doesn’t work: I have to declare the operator as a pure virtual method, in an abstract class that all other classes derive from.

#include<iostream>
using namespace std;

class Figabs {
protected:
    int fel;
public:
    int getFEL() { return fel; }
    virtual Figabs operator +()=0; /*this is where I get an error: function returning  abstract class “Figabs” is not allowed : function Figabs::operator+ is a pure virtual function */
};

class Coord {
public: 
    int cx, cy; 
public: 
    Coord (){ 
        cx = cy = 0;
    }

    Coord (const int x, const int y) {
        cx = x;
        cy = y;
    }

    Coord (const Coord &din) { 
        cx = din.cx;
        cy = din.cy;
    }

    ~Coord () { }
    void setX(const int val) { cx = val; } ;
    void setY(const int val) { cy = val; };
    int getX() { return cx; }
    int getY() { return cy; }
};

class Point : public Coord, public Figabs { //one of the figures

public:
    Point() { 
        setX(0);
        setY(0);
        fel = 0;
    }

    Point(const int x, const int y): Coord (x,y) { 
        fel = 0;
    } 

    Point(const Point &din): Coord (din) { 
        fel = din.fel; 
    } 

    ~Point() { } 

    Point operator +(const Coord &vector) { /*this works perfectly when I delete the declaration from the abstract class Figabs, but I don’t know how to make them work together */
        int xp = cx + vector.cx;
        int yp = cy + vector.cy;
        return (Point (xp, yp));
    }

    Point operator *(const Coord &vector) {
        Point temp;
        temp.cx = cx * vector.cx;
        temp.cy = cy * vector.cy;
        return (temp);
    } 
};

Thank you and please be patient with me, it is my first contact with C++.

Answer

James Kanze picture James Kanze · May 22, 2013

As other posters have pointed out, the assignment is far from trivial, and operator+ isn't normally a member. There are two issues which should be addressed:

  1. If you support `FigAbs + Coord`, then you should also support `Coord + FigAbs`. The first can be a member (there's no real problem there); the second, if it is to be a member, must be a member of `Coord`, which is probably not what is wanted.
  2. Any reasonable implementation of `operator+` must return by value. And you can't (normally) return a polymorphic class by value; you need something like the letter-envelope idiom for this to work: the base class must look something like:
    class Figure : BinaryOperators<Figure, Coord>
    {
        Figure* myImpl;
    public:
        Figure& operator+=( Coord const& translation )
        {
            myImpl->operator+=( translation );
            return *this;
        }
    };
    
    Of course, you'll need factory methods for correctly instantiating `Figure` for each different type, a virtual `clone` function, and copy constructor, assignment and destructor which support deep copy. (`BinaryOperators` is a template class which implements `operator+` in terms of `operator+=`; this is the usual way to provide the binary operators.)

Finally, I would argue that this is operator overloading abuse. The notion of addition doesn't apply to geometrical figures. What you're doing is called translation, and the logical solution is to provide a member function which does it, not to overload addition.