C++ How can I return an unknown derived class?

Jean

I have a base class Shape that has derived classes like Ellipse and Rectangle.

In one function, I have a variable:

Shape activeShape(black, black, {0,0}, {0,0}, false);

and later in that function:

activeShape = updateShape(isButton, activeShape, true);

updateShape looks like this:

Shape updateShape(int button, Shape active, bool leftClick)
{
    switch(button)
    {
        case 1:
            return active;
        case 2:
            return Line(active.getFillColor(), active.getBorderColor(), active.getP1(), active.getP2(),false);
            break;
        case 3:
            return Rectangle(active.getFillColor(), active.getBorderColor(), active.getP1(), active.getP2(),false);
            break;
        case 4:
            return FilledRectangle(active.getFillColor(), active.getBorderColor(), active.getP1(), active.getP2(),false);
            break;
        case 5:
            return Ellipse(active.getFillColor(), active.getBorderColor(), active.getP1(), active.getP2(),false);
            break;
        case 6:
            return FilledEllipse(active.getFillColor(), active.getBorderColor(), active.getP1(), active.getP2(),false);
            break;
        default:
            if(leftClick)
            {
                active.setColor(getEnumColor(button), active.getBorderColor());
            }
            else
                active.setColor(active.getFillColor(), getEnumColor(button));
            break;
    };
    return active;
}

So as I'm returning things like Rectangle, they are being casted as a Shape. Which is exactly not what I want.

What do I need to do to get activeShape to become one of Shapes derived classes?

Peter

Once an object is created, it is not possible to morph its type (e.g. based on information about a button obtained at run time). Returning a Rectangle as a Shape has the effect of slicing the object, so the caller only receives a copy of the Shape part of the Rectangle, but not the remaining parts.

Assuming Shape is a polymorphic base class (i.e. it provides virtual functions that may be specialised by derived classes), a Shape * (pointer to shape) can point at a Rectangle. However, it is then necessary to manage lifetime of the object correctly.

You can deal with all this by using a smart pointer such as, in C++11 and later, std::unique_pointer<Shape>.

std::unique_pointer<Shape> updateShape(int button,
        std::unique_pointer<Shape> active, bool leftClick)
{
    switch(button)
    {
        case 1:
             break;    // don't change active
        case 2:
            active = new Line(active->getFillColor(), active->getBorderColor(), active->getP1(), active->getP2(),false);
            break;
        case 3:
            active = new Rectangle(active->getFillColor(), active->getBorderColor(), active->getP1(), active->getP2(),false);
            break;
        case 4:
            active = new FilledRectangle(active->getFillColor(), active->getBorderColor(), active->getP1(), active->getP2(),false);
            break;
        case 5:
            active = new Ellipse(active->getFillColor(), active->getBorderColor(), active->getP1(), active->getP2(),false);
            break;
        case 6:
            active = new FilledEllipse(active->getFillColor(), active->getBorderColor(), active->getP1(), active->getP2(),false);
            break;
        default:
            if(leftClick)
            {
                active->setColor(getEnumColor(button), active->getBorderColor());
            }
            else
            {
                active->setColor(active->getFillColor(), getEnumColor(button));
            }
            break;
     }
     return active;
}

The reason this works is that std::unique_pointer manages the lifetime of a dynamically allocated (created with operator new) object. It does this by storing a pointer to the object, and assigning to a std::unique_pointer<Shape> changes the pointer (to make it point at a different object). Importantly, assigning to a smart pointer also releases the object it previously managed.

Note that, since std::unique_pointer will use operator delete to destroy the contained object when its lifetime is over, Shape MUST have a virtual destructor. Failure to do that will cause undefined behaviour on the use of operator delete.

The usage of this would go something like

 std::unique_pointer<Shape> activeShape(new Rectangle( whatever_parameters));

 activeShape = updateShape(button, activeShape, leftClick);

Bear in mind that activeShape is a smart pointer. So use of the contained Shape object requires pointer syntax (activeShape->whatever) not member syntax (activeShape.whatever).

Because the active parameter is passed (by value) to the function and returned, it is NECESSARY to assign the return value. If, instead of

activeShape = updateShape(button, activeShape, leftClick);

you simply

updateShape(button, activeShape, leftClick);   // returned object is discarded

(i.e. don't assign the return value to anything), the net effect is that the object held by activeShape will be destroyed, and any attempt to use it will give undefined behaviour.

Collected from the Internet

Please contact [email protected] to delete if infringement.

edited at
0

Comments

0 comments
Login to comment

Related

From Dev

How to pass a derived class to a base class function and return the derived class c#

From Dev

How can I friend a derived class function in the base class?

From Dev

How can I implement a Singleton class that can be derived from in WPF?

From Dev

How can I implement a Singleton class that can be derived from in WPF?

From Dev

How can I return a more derived type from an interface?

From Dev

How can I call virtual function definition of base class that have definitions in both abstract base class and derived class in C++?

From Dev

How can I combine templated derived class in CRTP with derived class expression templates?

From Dev

How can I find out which method of a derived class is not implemented?

From Dev

how can I obtain HWND of a class derived from QMainWindow

From Dev

How can I do constructor overloading in a derived class in TypeScript?

From Dev

How can I retrieve the derived class from a list of abstract classes?

From Dev

How can I "un-JsonIgnore" an attribute in a derived class?

From Dev

how can I obtain HWND of a class derived from QMainWindow

From Dev

How can I find out which method of a derived class is not implemented?

From Dev

How can I retrieve the derived class from a list of abstract classes?

From Dev

How can I access a method defined with new keyword in a derived class

From Dev

How can I call the constructor of the derived class when using CRTP?

From Dev

How do I return an auto_ptr of a base class using an auto_ptr of a derived class?

From Dev

How do I return an auto_ptr of a base class using an auto_ptr of a derived class?

From Dev

Why can't I return a reference to a unique_ptr of a derived class created with a template?

From Dev

How can I return self in a class method?

From Dev

How to return derived type while operating over base and derived class?

From Dev

Can a Base Class Method return the type of the derived class?

From Dev

Can I cast a derived class to a private base class, using C-style cast?

From Dev

C++11: Can I explicitly call a base class destructor to destroy the derived class?

From Dev

How can I store in a derived class information obtained during initialization of a base class?

From Dev

How can I create an instance of a derived class from an instance of a base class and include private fields?

From Dev

How can I initialize an instance of a derived class from an instance of the base class?

From Dev

How can I have an object of a derived class "reference" members of an instance of the base class?

Related Related

  1. 1

    How to pass a derived class to a base class function and return the derived class c#

  2. 2

    How can I friend a derived class function in the base class?

  3. 3

    How can I implement a Singleton class that can be derived from in WPF?

  4. 4

    How can I implement a Singleton class that can be derived from in WPF?

  5. 5

    How can I return a more derived type from an interface?

  6. 6

    How can I call virtual function definition of base class that have definitions in both abstract base class and derived class in C++?

  7. 7

    How can I combine templated derived class in CRTP with derived class expression templates?

  8. 8

    How can I find out which method of a derived class is not implemented?

  9. 9

    how can I obtain HWND of a class derived from QMainWindow

  10. 10

    How can I do constructor overloading in a derived class in TypeScript?

  11. 11

    How can I retrieve the derived class from a list of abstract classes?

  12. 12

    How can I "un-JsonIgnore" an attribute in a derived class?

  13. 13

    how can I obtain HWND of a class derived from QMainWindow

  14. 14

    How can I find out which method of a derived class is not implemented?

  15. 15

    How can I retrieve the derived class from a list of abstract classes?

  16. 16

    How can I access a method defined with new keyword in a derived class

  17. 17

    How can I call the constructor of the derived class when using CRTP?

  18. 18

    How do I return an auto_ptr of a base class using an auto_ptr of a derived class?

  19. 19

    How do I return an auto_ptr of a base class using an auto_ptr of a derived class?

  20. 20

    Why can't I return a reference to a unique_ptr of a derived class created with a template?

  21. 21

    How can I return self in a class method?

  22. 22

    How to return derived type while operating over base and derived class?

  23. 23

    Can a Base Class Method return the type of the derived class?

  24. 24

    Can I cast a derived class to a private base class, using C-style cast?

  25. 25

    C++11: Can I explicitly call a base class destructor to destroy the derived class?

  26. 26

    How can I store in a derived class information obtained during initialization of a base class?

  27. 27

    How can I create an instance of a derived class from an instance of a base class and include private fields?

  28. 28

    How can I initialize an instance of a derived class from an instance of the base class?

  29. 29

    How can I have an object of a derived class "reference" members of an instance of the base class?

HotTag

Archive