1

I have a class called Action, and a MoveAction which derives from Action and I have an object which holds a variable: Action action_to_perform. Now I assigned a new MoveAction to this variable. These Action classes holds a method perform(). MoveAction does something else than Action's perform. When I call

object->action_to_perform

then it calls Action's perform method, when it's set to a MoveAction object. How can I automatically cast it a MoveAction?

EDIT:

Action.h:

class Action
{
public:
    Action();
    virtual ~Action();

    virtual void perform();
protected:
private:
};

MoveAction.h:

class MoveAction : public Action
{
public:
    MoveAction(int, int);
    virtual ~MoveAction();

    int dx, dy;

    virtual void perform();
protected:
private:
};

In Player.cpp:

Action action_to_perform;
...
action_to_perform = MoveAction(0, 1);
RobeeZ
  • 95
  • 9
  • Have you declared the function virtual? Show some code – W.B. Aug 19 '14 at 18:54
  • Yea, perform is declared as virtual. I added some code that shows what I meant – RobeeZ Aug 19 '14 at 18:55
  • 7
    Use pointers to action if you want to preserve virtual behaviour - what you did is truly slicing, your `action_to_perform = MoveAction(0,1)` is actually using `Action::operator = (const Action&)` which slices the object - VMT of Action, not of MoveAction) – firda Aug 19 '14 at 19:06
  • 1
    To help avoid doing this, make Action pure virtual. Declare perform as `virtual void perform() = 0;` – Zan Lynx Aug 19 '14 at 19:41
  • Duplicate of [what is the slicing problem in C++](http://stackoverflow.com/questions/274626/what-is-the-slicing-problem-in-c). Reopened for some strange reason. – juanchopanza Aug 19 '14 at 20:40

1 Answers1

3

You are experiencing the problem of object slicing.

You need to store a pointer to Action.

Action* action_to_perform = NULL;
...
action_to_perform = new MoveAction(0, 1);
action_to_perform->perform();

should work.

To simplify memory management, it is better to store a smart pointer, such as shared_ptr or unique_ptr.

std::unique_ptr<Action> action_to_perform;
...
action_to_perform.reset(new MoveAction(0, 1));
action_to_perform->perform();
Community
  • 1
  • 1
R Sahu
  • 204,454
  • 14
  • 159
  • 270
  • 1
    References also work, though not in the OPs specific use case. I'd also suggest the use of some type of smart pointer (`shared_ptr`, `unique_ptr`, etc.) – Chad Aug 19 '14 at 20:06