Pure virtual operator
Asked Answered
B

3

12

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++.

Babism answered 22/5, 2013 at 10:42 Comment(17)
Did you try putting that declaration in the .H file instead?Ten
@Shark: what would that change exactly?Clingfish
virtual Figabs operator +()=0 with no arguments -> Point operator +(const Coord &vector) with different type returned? their signature has to be the same...Tricky
@Mat: nothing. fair enough :) Ok, lemme try again virtual Figabs operator +(const Figabs& rhs)=0 perhaps? :)Ten
I'm still grasping to understand what you're expecting with no RHS of that operator-abstract? (or did I miss something) ? Your retval will slice even if you do provide a proper op, btw. For a first-time C++ question, you're hitting a lot of subtle issues, so gratz for that =PQuintuplicate
try... and Point::operator+ has to return a Figabs& tooTricky
This is a slightly tricky problem, because operator+ should return an object (not a reference), so it can't return an abstract class (which Figabs is here because it has a pure virtual function). This is tricky to solve within the constraints of the assignment, at least partly because the assignment is enforcing bad design. operator+ should generally not be a member function (GOTW #4, part 5).Precognition
@Precognition It's tricky to solve because overloads of the binary operators must return by value, and return by value and polymorphism don't work well together. At all.Pomfret
@JamesKanze now i understand the full stack of problems this causes... it'll be interesting seeing how this gets solved :)Ten
Thank you for the quick reactions. The assignment seems to be trying to take me trough as much as the theory as possible. I am mostly wondering in the dark, could you someone maybe guide me step by step through the problem since i'm not really understanding the issues brought up by you?Babism
The real problem i see right now is the failure to implement the operator at all. Without that implementation, technically Point is a abstract class and as such cannot be value-returned from the operator you are defining (which is clearly different than what is specified in your abstract-base). The reason it "works" when that op is removed is simply because Point is no longer abstract. James' answer hits pretty solid on this.Quintuplicate
@Babism The problem is that the problem itself is asking you to do something that is very, very difficult, and which is probably wrong to begin with. This suggests that whoever thought up the problem probably shouldn't be teaching.Pomfret
For those who want to see how to really go about implementing things like operator+ over a class hierarchy: this problem is addressed in Advanced Programming Styles and Idioms_, by James Coplien. The book itself is pretty dated, but as far as I know, no one has come up with a better solution for this particular problem since it was written.Pomfret
Well, i am starting to think my approach to the problem must be wrong..could i instead put a pure virtual method called translation in the abstract class and then in every derived class overload the operator + with that function. Is that possible?Babism
@JamesKanze would it be possible to summarize Coplien's solution, to help me decide whether to get the book?Halcomb
@Halcomb Summarizing a hundred pages or so is far from simple, but the basic principle is that the base class acts like a handle: it has a protected constructor (only, except for public copy), which takes a Base* as an argument. All of the constructors of derived classes are private, and there are public static factory functions, along the lines of Base Derived::construct(...) { return Base( new Derived ); }. The Base uses the clone function to do a deep copy in assignment and the copy constructor, and deletes what it points to in the destructor.Pomfret
"I have to overload the operators +" please indicate if you mean unary or binary operator+.Organza
P
9

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.

Pomfret answered 22/5, 2013 at 11:7 Comment(0)
I
3

Figabs contains a pure virtual member function virtual Figabs operator +()=0; this means you cannot instantiate Figabs

consider:

virtual Figabs& operator +()=0; 
/*Now you will not be returning an actual instance but can return derived class instances*
Interlocution answered 22/5, 2013 at 10:49 Comment(3)
To where will that return value refer?Precognition
Thank you, that made the error go away, but now the derived class, where i have: Puncte operator +(const Coord &vector) says error: return type is not identical to nor covariant with return type Figabs& of overridden virtual function Figab::operator+Babism
@Precognition I totally see and agree. This is a very specific answer drawing attention to the cause of the compiler error not a complete solution to the problem.Interlocution
S
0

Please take a look at the following link for useful info bit related to question

overriding virtual function return type differs and is not covariant

virtual Figabs operator +() = 0;//Here ur not passing any i/p parameters

But in derived class ur passing parameters

Point operator +(const Coord &vector)//here ur sending i/p parameter .
Sheila answered 22/5, 2013 at 10:49 Comment(1)
This is more of a comment than an answer.Ten

© 2022 - 2024 — McMap. All rights reserved.