在c++代码中,InputMap的双调度失败——简化为简单

Double dispatching fails for an InputMap in C++ - codes reduced to simplicity

本文关键字:失败 简单 调度 代码 c++ InputMap      更新时间:2023-10-16

你好,在我当前的一个项目中,我想实现一个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;
};

这里是衍生的InputMap

//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),但不幸的是,默认处理程序总是被调用。我是否对这个模式进行了错误的编程?谢谢大家,我一直盯着我的代码,但我没有看到它。

您应该阅读访问者模式。

基本上,问题是虚函数是静态绑定的(讽刺),所以解决方案是在InputMap中声明所有HandleInput(对于每种Input类型)。

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

注意:惯例是使用纯虚方法,这样派生类就不会忘记重写一个。

当然,这会导致依赖关系的问题。幸运的是,您可以在包含InputMap的头文件中转发声明"真正的"输入类型。

有更复杂的变化(搜索无环访问者),但你现在不应该需要它:)

静态类型上执行函数查找和重载解析。因此,当您在StringInput::Dispatch()中输入pMap->HandleInput(*this)时,这总是会发现InputMap::HandleInput(Input &)过载,因为pMap是静态类型InputMap。然后动态地分配给覆盖MyInputMap::HandleInput(Input &)

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