0

I have a hierarchy of Figure as base class and several sub classes Circle, Square, ecc. I want to overload < operator in Figure to sort Figures by eg. Surface which is implemented in base classes.

This is my code:

//Figure.hpp
class Figure
{
public:
    virtual float surface() const = 0;
    virtual float perimeter() const = 0;

    friend bool operator<(const Figure& lhs, const Figure& rhs);
    friend bool operator>=(const Figure& lhs, const Figure& rhs);
}

//Figure.cpp
bool operator<(const Figure& lhs, const Figure& rhs)
{
    return lhs.surface() < rhs.surface();
}

bool operator>=(const Figure& lhs, const Figure& rhs)
{
    return lhs.surface() >= rhs.surface();
}

//Square.hpp
class Square : public Figure{
public:
    Square(float size);
    float surface() const{
        return mSize * mSize;
    };
    float perimeter()const{
        return mSize * 4;
    }
private:
    float mSize;
};

Problem is I get an error at runtime:

libc++abi.dylib: Pure virtual function called!

at lhs.surface().

I call the < operator in a LinkedList with Template:

template <typename T>
void List<T>::insertNewNode(T& dataIn) 
{
    if(isEmpty()) 
    {
        insertBegin(dataIn);
    }else //otherwise
    {
        if(dataIn < *startPtr->data) 
        {
            insertBegin(dataIn);
        }
        else if(dataIn >= *endPtr->data) /
        {
            insertEnd(dataIn);
        }
        else 
        {
            //...
        }
    }
}

//main.cpp
List<Figure> *list = new List<Figure>();
Figure *square = new Square(46);
list->insertNewNode(*square);

EDIT https://github.com/sanandrea/GenericLinkedList

Is this feasible or I am doing everything wrong?

rmaddy
  • 314,917
  • 42
  • 532
  • 579
Sanandrea
  • 2,112
  • 1
  • 27
  • 45
  • Can you show some code that calls either operator? You aren't doing it in Square's constructor or destructor, right? – simon Jan 05 '17 at 17:43
  • 2
    Cannot reproduce / not real code / does not compile and link. In any case, it's typically a bad idea to add operator overloading to OOP classes (i.e. classes with virtual functions), whose instances are often accessed via pointers or smart pointers. Your classes should either not have overloaded operators or not have virtual functions. – Christian Hackl Jan 05 '17 at 17:46
  • [This](http://stackoverflow.com/questions/34051749/how-to-track-down-libcabi-dylib-pure-virtual-function-called-in-xcode) might be related. But the originally posted code seems ok in general as it works [here](http://coliru.stacked-crooked.com/a/9180b852babf66c6) with minor modifications. – wally Jan 05 '17 at 17:50
  • Could you post a complete single program that generates the error? My guess is that as you put the various elements together to create an [mcve](stackoverflow.com/help/mcve) you will probably find the problem. – wally Jan 05 '17 at 17:53
  • So, in theory it is feasible? – Sanandrea Jan 05 '17 at 17:54
  • By the way, you still have object slicing here: `T ListNode::getData() ` in ListNode.hpp – simon Jan 05 '17 at 18:18

1 Answers1

3

The problem is both Object Slicing and undefined behavior.

You insert values via

void List<T>::insertNewNode(T& dataIn)

which is OK. Since you pass it by reference the polymorphism will be kept. However, when you later call insertBegin or insertEnd to actually create the node you pass it by T:

void List<T>::insertBegin(T dataIn)

Here dataIn have lost the polymorphism due to Object Slicing. You also have undefined behavior when you store a pointer to the parameter in the newly created node:

ListNode<T> * newPtr = new ListNode<T>(&dataIn); //creates new node

Note that &dataIn is a pointer to the parameter of insertBegin, not a pointer to the dataIn that was passed in insertNewNode(T& dataIn).

You also have Object Slicing in your node: T ListNode<T>::getData() //returns data stored in node.

simon
  • 2,042
  • 2
  • 20
  • 31