对于C ++中的InputMap,双重调度失败 - 代码简化为简单

时间:2011-09-14 14:09:25

标签: c++ polymorphism handler double-dispatch

你好我当前的一个项目我想实现一个InputMap。所以我有一个抽象的输入

//Input.h
namespace INPUT {
class InputMap;
class Input {
public:
    Input();
    virtual ~Input();
    virtual void Dispatch( InputMap * pMap ) = 0;
};
}

和一个InputMap

//InputMap.h
namespace INPUT {
class InputMap {
public:
    InputMap();
    virtual void HandleInput( INPUT::Input & anInput ) {
    }
    virtual ~InputMap();
};
}

到目前为止一直很好 - 这里没有功能。现在我从抽象输入类派生出我的第一个真正的输入:

//StringInput.h
#include "Input.h"
#include "InputMap.h"
#include <string>

class StringInput : INPUT::Input {
public:
    StringInput();
    virtual ~StringInput();
    void Dispatch(INPUT::InputMap * pMap)
    {
        pMap->HandleInput( *this );
    }
    void SetMessage(std::string message);
    std::string GetMessage() const;
private:
     std::string m_message;
};

这是我的派生输入地图

//MyInputMap.h
#include "InputMap.h"
#include "StringInput.h"

class MyInputMap: public INPUT::InputMap {
public:
    MyInputMap();
    void HandleInput( StringInput & anInput );
    void HandleInput( INPUT::Input & anInput );
    virtual ~MyInputMap();
};

这是测试:

//main.cpp
MyInputMap map;
StringInput input;
input.SetMessage("Test");
input.Dispatch(&map);

当然我希望input.Dispatch(&map)调用map.HandleInput(StringInput input),但遗憾的是始终会调用默认处理程序。我编程这种模式错了吗?谢谢大家,我一直在盯着我的代码,但我没有看到它。

2 个答案:

答案 0 :(得分:2)

您应该阅读Visitor模式。

基本上,问题是虚函数是静态绑定的(具有讽刺意味),因此解决方案是在HandleInput中声明所有Input(对于InputMap}中的每一种类型。 / p>

class InputMap {
public:
    InputMap();
    virtual void HandleInput(StringInput&) = 0;
    virtual void HandleInput(IntInput&) = 0;
    virtual ~InputMap();
};

注意:约定是使用纯虚方法,因此没有派生类忘记覆盖它。

当然,这会导致依赖性问题。幸运的是,您可以在包含InputMap的标头中转发声明“真实”输入类型。

有更复杂的变体(搜索非循环访客),但你现在不需要它:)

答案 1 :(得分:0)

静态类型上执行函数查找和重载解析。因此,当您在pMap->HandleInput(*this)中说StringInput::Dispatch()时,总会发现InputMap::HandleInput(Input &)重载,因为pMap属于静态类型InputMap。然后将其动态分派到覆盖MyInputMap::HandleInput(Input &)

解决此问题的一种方法是在(唯一)HandleInput()函数中添加动态调度,该函数在运行时确定参数的动态类型。