2011-09-14 10 views
1

こんにちはに縮小コードを。ここには機能 - だから私は、とても良い、これまで抽象入力ダブルディスパッチは、C++でのInputMapのために失敗した - 私は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(); 
}; 
} 

を持っています。今、私は私の抽象入力クラスからの私の最初の本当の入力を導き出す:私は期待して当然の

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

//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(); 
}; 

、ここではテストですそのinput.Dispatch(&map)map.HandleInput(StringInput input)を呼び出しますが、残念ながらデフォルトのハンドラが常に呼び出されます。私はこのパターンを間違ってプログラムしましたか?ありがとう、私は永遠に私のコードを見てきましたが、私はそれを見ません。関数ルックアップとオーバーロード解決

+0

あなたは今、それを必要はありません。 –

+2

'INPUT'には注意してください。あなたは、マクロとの衝突を見つけ出すかもしれません。大会では、マクロはすべて大文字であるため、避けることをお勧めします。 –

+0

は実際に私は、私はちょうどこの周りだと思う:私はちょうど私のクラスのStringInputに派遣(MyInputMap * PMAP)を追加しました:INPUT ::入力し、今私が動作するようです。 –

答えて

2

あなたはVisitorパターンについてお読みください。

基本的には、仮想関数が静的に(アイロニクに)バインドされているという問題があります。そのため、解決方法はにすべて(すべての単一タイプのInput)を宣言することです。

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

注:大会は何の派生クラスは、1を上書きするのを忘れないように、純粋仮想メソッドを使用することです。もちろん

、これは、依存関係の問題が発生します。幸いにも、InputMapを含むヘッダーに "実際の"入力タイプを宣言することができます。

より複雑なバリエーションが(非環式ビジターの検索)がありますが、私はあなたが `&`あなたの最後の段落でを忘れてしまったと思います:)

+0

どのようにしてこの猫をスキンしても、始めから具体的なタイプをいつも知っている必要があります...非周期的な訪問者は、成功するまで動的キャストのリストを調べることを犠牲にして、 –

+0

@Kerrek:そうですね、私はたいてい弾を噛んで、典型的な「ビジター」を使用しています。 –

+0

実際に私はちょうどこの周りにいると思う:私は私のクラスStringInputにディスパッチ(MyInputMap * pMap)を追加しました:INPUT :: Inputそして今私は動作するようです。つまり、私のBaseClassesはInputMapとInputの両方に派生型がまったくないことを意味します。これはあなたの経験に意味がありますか? –

0

静的タイプ上で実行されます。あなたはStringInput::Dispatch()pMap->HandleInput(*this)言うときpMapは、静的な型InputMapであるためので、これは常に、InputMap::HandleInput(Input &)過負荷を検出します。これは、オーバーライドMyInputMap::HandleInput(Input &)に動的にディスパッチされます。

これを克服する1つの方法は、(ユニークな)HandleInput()関数内に動的ディスパッチを追加して、実行時に引数の動的な型を決定することです。

関連する問題

 関連する問題