2

I have the following class hierarchy:

#include <iostream>

using namespace std;

class Figure
{
    public:
    Figure() {};
    virtual void print() const { cout << "Figure" << endl; };

    Figure& operator=(const Figure& rhs)
    {
        if (this != &rhs)
        {
            cout << "Called figure equals" << endl;
        }

        return *this;
    };
};

class Circle : public Figure
{

public:
    Circle() {};
    virtual void print() const { cout << "Circle" << endl; };

    Circle& operator=(const Circle& rhs)
    {
        if (this != &rhs)
        {
            Figure::operator=(rhs);
            cout << "Called circle equals" << endl;
        }

        return *this;
    };
};

And when im adding derived objects to the FigureContainer, objects are not using its own operator=, but they're using the base class oprerator and enters in the array as base class instaces, so i cant call "print" function from the derived class.

class FigureContainer
{
public:

    FigureContainer() { };

    int size = 0;
    Figure figures[20];

    void add(const Figure& figure)
    {
        figure.print(); // Called circle print !
        figures[size] = figure; // Used base = operator instead of the derived figure class
        size++;
    };
};

int main()
{
    FigureContainer* figures = new FigureContainer();

    (*figures).add(*new Circle());

    (*figures).figures[0].print(); // called abstract print !

    system("pause");
    return 0;
}

.

Output :
Circle
Called figure equals
Figure

What am I doing wrong?

  • Possible duplicate of [virtual assignment operator C++](http://stackoverflow.com/questions/669818/virtual-assignment-operator-c) – LogicStuff Jun 26 '16 at 14:49
  • 3
    You've written a memory leak machine. You shouldn't use `new` if you don't know what it does. – juanchopanza Jun 26 '16 at 14:49

1 Answers1

2

In C++ operator = is not virtual. The compiler determines what class will supply the operator at compile-time. The assignment figures[i] = ... is handled by the type of the left-hand side object, hence Figure's operator is called.

This is OK because non-pointer assignments are not supposed to be polymorphic: an array of Figure objects can store only Figure objects without object slicing. Storing a Circle removes all circle-specific properties of the object, leaving you with only the Figure parts.

You can fix this by making figures an array of smart pointers. This would preserve the subtype of the object stored in the container, and it would make the problem of which assignment operator to use irrelevant.

Sergey Kalinichenko
  • 714,442
  • 84
  • 1,110
  • 1,523
  • Thanks, but im not allowed to use smart pointers. I dont really get the idea why this shouldn work, thats the whole point of the polymorphism. – Zdravko Georgiev Jun 26 '16 at 15:35
  • @ZdravkoGeorgiev Polymorphic behavior is available only with pointers, smart or built-in, and references. Regular objects do not have polymorphic behavior due to object slicing. Look it up on wiki or on stack overflow to see what's going on, and how it breaks polymorphism. – Sergey Kalinichenko Jun 26 '16 at 15:58
  • I solved the problem like this: void add(string shape, string shapeParams) if(shape == "circle) figures[size] = new Circle(shapeParams); ... Worked like charm. – Zdravko Georgiev Jun 26 '16 at 19:08