C++ 中的抽象类问题撤消/重做实施
我定义了一个“Action”纯抽象类,如下所示:
class Action {
public:
virtual void execute () = 0;
virtual void revert () = 0;
virtual ~Action () = 0;
};
并表示用户可以使用类执行的每个命令。
对于实际的撤消/重做,我想做这样的事情:
Undo
Action a = historyStack.pop();
a.revert();
undoneStack.push(a);
Redo
Action a = undoneStack.pop();
a.execute();
historyStack.push(a);
编译器显然不接受这一点,因为“Action”是一个抽象类,不能实例化了。
那么,我是否必须重新设计一切,或者是否有一个简单的解决方案来解决这个问题?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
您应该将操作存储为指针,这将使编译器满意。
std::vector 之所以如此,还有另一个原因。 HistoryStack;
将不起作用,这就是切片。当将派生类的对象添加到向量时,它们将被转换为基类并释放其所有多态性。有关更多信息,请参阅:什么是对象切片?编辑 研究使用 ptr_vector 来管理向量中对象的生命周期:http://www.boost.org/doc/libs/1_37_0/libs/ptr_container/doc/tutorial.html
You should store actions as pointers, that will keep the compiler happy.
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
无论如何,多态调度仅通过 C++ 中的指针或引用发生。您可能无法创建 Action 的值,但您会发现您将能够创建对 Actions 的引用和指针。
pop 只需要返回一个(可能是智能的)指针,或者一个指向 Action 的引用。一种方法可能是使用 std::auto_ptr 和 boost ::ptr_deque,这将(正确使用)确保操作之后得到适当的清理。
另一个选项可以是
boost::shared_ptr
的std::stack
或类似的。或者您可以只使用原始指针,但必须小心所有权的管理是否正确。Polymorphic dispatch only happens through pointers or references in C++ anyway. You may not be able to create a value of Action, but you will find you'll be able to create references and pointers to Actions.
pop merely needs to return a (possibly smart) pointer, or a reference, to an Action. One approach might be to use std::auto_ptr and boost::ptr_deque, this will (with correct usage) ensure that the actions are appropriately cleaned up after.
Another option could be a
std::stack
ofboost::shared_ptr<Action>
or similar. Or you can just use raw pointers, but you must be careful that ownership is managed correctly.您应该在队列中存储指向已执行操作的指针。
例如:
然后:
并且:
当然,您应该使用 new 和 delete 为实际的 Action 对象创建和释放内存,但我不这样做认为您可以将 auto_ptr 与标准容器一起使用,因此您必须手动管理内存或实现其他方法。但如果您将撤消缓冲区包装在一个类中,这应该不是一个大问题。
You should store pointers to performed operations in the queue.
For instance:
Then:
And:
Of course you should use new and delete to create and free memory for actual Action objects and I don't think you can use auto_ptr with standard containers so you have to manage your memory manually or implement some other method. But this should not be a big problem if you wrap undo buffer in a class.