I have defined an "Action" pure abstract class like this:
class Action {
public:
virtual void execute () = 0;
virtual void revert () = 0;
virtual ~Action () = 0;
};
And represented each command the user can execute with a class.
For actual undo/redo I would like to do something like this:
Undo
Action a = historyStack.pop();
a.revert();
undoneStack.push(a);
Redo
Action a = undoneStack.pop();
a.execute();
historyStack.push(a);
The compiler obviously does not accept this, because "Action" is an abstract class which can not be istantiated.
So, do I have to redesign everything or is there a simple solution to this problem?
You should store actions as pointers, that will keep the compiler happy.
std::vector<Action*> historyStack;
/*...*/
historyStack.push_back(new EditAction(/*...*/));
Action* a = historyStack.pop();
a->revert();
undoneStack.push(a);
There is another reason why std::vector<Action> historyStack;
will not work and that's slicing. When adding objects of derived classes to the vector they will be cast to the base class and loose all their polymorphism. More about it here: What is object slicing?
EDIT Look into using ptr_vector to manage the lifetime of the objects in the vector: http://www.boost.org/doc/libs/1_37_0/libs/ptr_container/doc/tutorial.html