4

在构造函数上初始化一个名为 ManageRenderListenerCommand 的类时,我在 C++(MVS 2010)上遇到了异常行为。这是作为命令设计模式实现的,其中 ManageRenderListenerCommand 命令是具体命令之一。

我称之为 ManageRenderListenerCommand 的地方

void Mediator::change(Negotiator* negotiator, NegotiatorEvent& negotiatorEvent){
    ICommand* command = NULL;
    if(negotiatorEvent.matchEvent("addToViewport")){
        command = static_cast<ICommand*> (&AddToViewportCommand(mCameraManager, mSceneCreator, mEngine));
    }else if (negotiatorEvent.matchEvent("manageRenderListener")){
        command = static_cast<ICommand*> (&ManageRenderListenerCommand(mObserverRegistry, mEngine, negotiatorEvent.getMessage()));
    }

    //Execute the created command
    if (command) command->execute();
}

negotiatorEvent.getMessage()正如您在代码中看到的,ManageRenderListener 接收一个字符串,在这种情况下,该字符串包含 NegotiatorEvent 类 ( )中包含的单词 add 。

问题是,在构造函数上,我将字符串放在私有成员上,但是在分配和强制转换之后我可以看到调试被删除并重新初始化为“”。我试过static_cast、dynamic_cast。为了提供线索,我认为这是一个可见性问题,但我不知道如何管理它。

}else if (negotiatorEvent.matchEvent("manageRenderListener")){
    //Here mMessage = ""
    command = static_cast<ICommand*> (&ManageRenderListenerCommand(mObserverRegistry, mEngine, negotiatorEvent.getMessage()));
    //Here mMessage is again "" instead of add
}

管理渲染监听器.cpp

#include "ManageRenderListenerCommand.h"

ManageRenderListenerCommand::ManageRenderListenerCommand(
    OgreRenderObserverRegistry* observerRegistry, 
    OgreEngine* engine,
    string message):
        mObserverRegistry(observerRegistry),
        mEngine(engine),
        mMessage(message){
}

void ManageRenderListenerCommand::execute(){
    if (mMessage.compare("add") == 0){
        mEngine->addRenderListener(mObserverRegistry->getCachedObserver());
    }else if (mMessage.compare("detach") == 0){
        mEngine->detachRenderListener(mObserverRegistry->getCachedObserver());
    }
}

如果您需要更多详细信息,请索取。谢谢你的帮助。

4

2 回答 2

6

你正在使用一个悬空指针。您正在使用的对象构造会创建一个临时对象,该对象在完整表达式 (the static_cast) 结束时被销毁。你仍然有一个指向它所在位置的指针(in command),但对象本身已经被销毁了。

您需要以某种方式创建命令,使其持续到调用execute(). 如果代码如您所示,您可以简单地执行以下操作:

if(negotiatorEvent.matchEvent("addToViewport")){
    AddToViewportCommand(mCameraManager, mSceneCreator, mEngine).execute();
}else if (negotiatorEvent.matchEvent("manageRenderListener")){
    ManageRenderListenerCommand(mObserverRegistry, mEngine, negotiatorEvent.getMessage()).execute();
}

如果在创建和调用之间有更多步骤execute(),您可能必须动态创建命令:

void Mediator::change(Negotiator* negotiator, NegotiatorEvent& negotiatorEvent){
    ICommand* command = NULL;
    if(negotiatorEvent.matchEvent("addToViewport")){
        command = new AddToViewportCommand(mCameraManager, mSceneCreator, mEngine);
    }else if (negotiatorEvent.matchEvent("manageRenderListener")){
        command = new ManageRenderListenerCommand(mObserverRegistry, mEngine, negotiatorEvent.getMessage());
    }

    //Execute the created command
    if (command) command->execute();

    delete command;
}

如果您有权访问 C++11,请使用std::unique_ptr<ICommand>forcommand而不是原始指针。

于 2013-03-25T08:43:33.377 回答
1

我认为您要做的是初始化一个在 c'tor 中接受字符串的命令;您实际上所做的是强制命令成为字符串本身的地址。您需要使用运算符“new”创建一个新对象,如果您已经匹配了命令的类型,您应该能够启动特定的命令,并在 c'tor 中给它一个字符串,如:

command = new SomeICommand(ManageRenderListenerCommand(mObserverRegistry, mEngine, negotiatorEvent.getMessage());
于 2013-03-25T08:42:45.953 回答