在C ++中使用向量实现撤消/重做的问题

时间:2014-12-14 00:29:22

标签: c++ design-patterns vector command

我目前正在开发一个类的项目,我们正在使用C ++在文本编辑器中实现简单的功能。我们有简单的命令,例如插入一个字符,向左移动,插入一个新行,然后我们有一个撤销/重做功能,其中撤消只是撤消上一个命令的任何内容。并且重做将重做任何刚刚撤消的命令。

首先,我有一个名为Command的基类,我在其中派生了所有其他类来实现这些命令。到目前为止,我的每个命令都按预期工作,撤消和重做这些命令的简单组合将起作用。

我使用两个向量在我的CommandProcessor类中实现了undo / redo的功能:

std::vector<Command*> undoVector; // used for undo
std::vector<Command*> redoVector; // used for redo

发出命令时,它会转到if-else中的某个语句,并将该命令存储在undoVector中。在调用undo时,在撤消命令之前,我将该向量中的命令存储在redoVector中。当我重做命令时,我将命令重新存储在undoVector中并发出命令来执行它。

当用户点击退出时,我使用此方法释放向量内存:

void freeVector(std::vector<Command*> &element) {
    for(int i = 0; i < element.size(); i++)
    {
        delete element[i]; // delete command object
    }
    element.clear(); // clear vector
} // end free vector

在我的程序中,应该始终可以通过使用撤消来回到程序启动的状态,这看起来像这样(其中|是我的光标的位置):< / p>

1. |

目前,如果我发出太多命令要撤消,我会重做几个命令,然后我插入一些命令,撤消那些命令,然后重做那些命令,我​​无法撤消到我的开头程序。它被一个随机的命令所困,并且不再进一步。

运行memcheck,显示此错误:

==24048== Invalid free() / delete / delete[] / realloc()
==24048==    by 0x805CCE0: (anonymous namespace)::freeVector(std::__1::vector<Command*, std::__1::allocator<Command*> >&)

以下是我目前正在实现撤消和重做向量的方法。任何帮助将不胜感激。

void CommandProcessor::run()
{
    bool commandInteraction = false;
    std::vector<Command*> undoVector; // used for undo
    std::vector<Command*> redoVector; // used for redo
    view.refresh();
    while (true)
    {
        UserInteraction interaction = nextUserInteraction();
        if (interaction.type == UserInteractionType::quit)
        {
            break;
        }
        else if (interaction.type == UserInteractionType::undo) // UNDO
        {
            try
            {
                if(undoVector.empty())
                {
                    throw EditorException("Nothing to undo.");
                } else {
                    interaction.command = undoVector.back();
                    redoVector.push_back(interaction.command);
                    interaction.command->undo(editor);
                    commandInteraction = false;
                    undoVector.pop_back();
                }
            }
            catch (EditorException& e)
            {
                view.showErrorMessage(e.getReason());
            }
            view.refresh();
        }
        else if (interaction.type == UserInteractionType::redo) // REDO
        {
            try
            {
                // if the redo stack is empty -> we can't redo
                // if the last known state was at command -> we can't redo
                if(redoVector.empty() || commandInteraction == true)
                {
                    freeVector(redoVector);
                    throw EditorException("Nothing to redo.");
                } else {
                    interaction.command = redoVector.back();
                    undoVector.push_back(interaction.command);
                    interaction.command->execute(editor);
                    redoVector.pop_back();
                    view.clearErrorMessage();
                }
            }
            catch(EditorException& e)
            {
                view.showErrorMessage(e.getReason());
            }
            view.refresh();
        }
        else if (interaction.type == UserInteractionType::command) // COMMAND
        {
            try
            {
                interaction.command->execute(editor);
                commandInteraction = true;
                undoVector.push_back(interaction.command);
                delete interaction.command;
                view.clearErrorMessage();
            }
            catch (EditorException& e)
            {
                delete interaction.command;
                view.showErrorMessage(e.getReason());
            }
            view.refresh();
        }
    } // end while
    freeVector(undoVector);
    freeVector(redoVector);
} // end run

0 个答案:

没有答案