2013-06-06 25 views
5

私はC++にあまりよく似ていません(しかし、私はOOP/Javaに精通しています)が、私のC++クラス用のゲームを作成する必要があります。私は、ActionScriptで書かれたFlashゲームのような種類のゲームエンジンをセットアップしたいと思っています。C++ - メンバ関数への多態ポインタ

私は基底クラス(おそらく抽象的になります)とPlayerが実際にそれを実装する必要がありますようActorを意味している。この2つのクラスを、書きました。

addEventListenerhandleのコードが重複するのを避け、_handlerMapを再宣言したいので、データ隠蔽などを実現したいからです。

_eventMapには、Actor::*handlerPlayer::*handlerを変更できる値のhandlerが含まれている必要があります。出来ますか?

class Actor { 
    protected: 
     typedef void(Actor::*handler)(Event); 
     map<int, handler> _handlerMap; 
    public: 
     virtual void addEventListener(int ID, handler h) { 
      _handlerMap.insert(std::make_pair(ID, h)); 
     }; 
     virtual void handle(int ID) { 
      handler h = _handlerMap[ID]; 
      Event e; 
      if (h) 
       (this->*h)(e); 
     } 
     virtual void onUpdate(Event e) { 
      cout << "Actor::onUpdate()" << endl; 
     }; 
    }; 

class Player : public Actor { 
    typedef void(Player::*handler)(Event); 
    map<int, handler> _handlerMap; 
public: 
    void addEventListener(int ID, handler h) { 
     _handlerMap.insert(std::make_pair(ID, h)); 
    }; 
    void handle(int ID) { 
     handler h = _handlerMap[ID]; 
     Event e; 
     if (h) 
      (this->*h)(e); 
    } 
    void onKeydown(Event e) { 
     cout << "Player::onKeyDown()" << endl; 
    }; 
}; 

私はとプレイヤーを宣言することが可能であった希望:私はあなたが理解してほしい

class Player : public Actor { 
     typedef void(Player::*handler)(Event); 
public: 
     void onWhateverEvent(Event e); 
} 

。あなたはこのような何か(テストしていません)必要

+0

あなたは 'Actor'の他のインスタンスがハンドラを登録できるようにしたいですか? (つまり、 'addEventListener'はpublicメンバでなければなりません) – dyp

+0

"問題は、 '_eventMap'" - > '_handlerMap'を意味するのでしょうか? – dyp

+1

私が考えることができる最も簡単な解決策は、C++ 11で利用可能な 'std :: function'と' std :: bind'を使うことです。 – dyp

答えて

2

class Dispatcher { 
    public: 
    virtual void dispatchEvent(Event*) = 0; 
}; 

template <class C> 
class DispatcherImpl : public Dispatcher 
{ 
    typedef void(C::*handler)(Event* e); 
    std::map<int, handler> _handlerMap; 
    C* _owner; 
    public: 
    DispatcherImpl (C* c) : _owner(c) {} 
    addEventListener(int ID, handler h) { 
     _handlerMap.insert(std::make_pair(ID, h)); 
    }   
    void dispatchEvent(Event*) 
    { 
     handler h = handlerMap[e->id]; 
     if (h) (_owner->*h)(e); 
    } 
} 

は今、俳優の各タイプTDispatcherImpl<T>を所有してみましょう、あなたはすべてのセットです。たとえば、 PlayerDispatcherImpl<Player>を継承します。

+0

'dispatchEvent'は何かを返す必要があります。このイベントに対して 'Player'に特別なハンドラがない場合に' Player'が 'Actor'にイベントを渡すようにします。また、map :: operator []の代わりに 'map :: find'を使用して、要素がマップに存在するかどうかを確認したいと思います。 – dyp

+0

@DyP:絶対にありません。 'Player' *は' Actor'です。他の「Actor」に渡したいものは何ですか? 'map :: find'に関しては、確かにそれを使用してください。このスニペットは厳密には擬似コードであり、文字通り使用されることはありません。 –

+0

派生型だけが 'DispatcherImpl'から継承する必要があることを意味していますか?私は、あなたが「俳優」もそれから派生しなければならないことを意味していると思ったその場合は、あなたは返品する必要があります。イベントIDが現在の_handlerMapで見つかったかどうかを示す 'dispatchEvent'からの' bool'、または処理されるベースクラスのディスパッチャーに渡されるべきかどうかを示します。 – dyp

0

あなたはこれについてどう思いますか?ただ、それを使用するには

template <class T> 
class Entity { 
    T *_instance; 
    Dispatcher<T> *_dispatcher; 
public: 
    Entity() { 
     _instance = new T(); 
     _dispatcher = new Dispatcher<T>(_instance); 
    } 
}; 
class Actor { 
    //attirbutes and methods 
}; 
class Player : public Actor { 
    //attirbutes and methods 
}; 

(ディスパッチャは、上記DispatcherImplと同じです):

Entity<Actor> *actor = new Entity<Actor>(); 
Entity<Player> *player = new Entity<Player>(); 
actor->getDispatcher()->addEventListener(0, &Actor::foo); 
player->getDispatcher()->addEventListener(1, &Player::bar); 
player->getDispatcher()->addEventListener(0, &Actor::foo); //inheritance 
関連する問題