2013-06-06 28 views
5

C++'da pek iyi değilim (ama OOP/Java'yı tanıyorum) ama C++ sınıfım için bir oyun oluşturmam gerekiyor. ActionScript'te yazılmış Flash oyunlar için kullanılan bir tür oyun motoru kurmak istiyorum. C++ - Üye işlevlerine polimorfik işaretçi

ben (muhtemelen soyut olacaktır) ve Player aslında uygulamalıdır Actor bir temel sınıf olarak içindir bu iki sınıf yazdı.

sorun

ben veri saklamayı ve bu tür şeyleri başarmak istiyoruz çünkü fonksiyonları addEventListener ve handle ve _handlerMap yeniden ilan yinelenen kod önlemek istiyorum olmasıdır.

sorun, sanırım, _eventMap sınıf Actor::*handler ve Player::*handler değiştirebilir handler değerleri içeren gerektiğidir. Mümkün mü?

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; 
    }; 
}; 

Ben o kadar Player bildirmek mümkün olsaydı:

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

Umarım anlarsın.

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

Şimdi aktörün her tür T bir DispatcherImpl<T> kendi edelim ve tüm ayarlanır:

+0

bir işleyici kayıt 'Actor' diğer örneklerini izin vermek istiyor musunuz:

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 }; 

sadece Kullanmak için (Dispatcher yukarıdaki DispatcherImpl aynıdır)? (yani, addEventListener’ın halka açık olması gerekir mi?) – dyp

+0

"Sorun, sanırım" _eventMap' "-> _handlerMap' anlamına mı geliyor? – dyp

+1

Düşünebildiğim en basit çözüm, C++ 11'de bulunan 'std :: function' ve' std :: bind' kullanmaktır. – dyp

cevap

2

Böyle bir şey (test) gerekir. Ayrıca, örn. Player, DispatcherImpl<Player>'dan devralmıştır.

+0

'dispatchEvent', örn. Bu etkinlik için 'Player'da özel bir işleyici yoksa 'Oyuncu' etkinliği 'Aktör'e geçirsin. Ek olarak, haritadaki bir öğenin olup olmadığını kontrol etmek için 'map :: operator []' yerine 'map :: find 'kullanmayı tercih ederim. – dyp

+0

@DyP: kesinlikle değil. Bir Oyuncu * * * bir Aktördür. Başka hangi aktörlere geçmek istiyorsun? 'Map :: find' için olduğu gibi kullanın. Bu snippet kelimenin tam anlamıyla kullanılmaması için kesinlikle pseudocode'tur. –

+0

Sadece türetilmiş türler DispatcherImpl'den mi devralmalıdır? Ben de 'Aktör'ün bundan türetilmesi gerektiğini' düşündüğümüzü; Bu durumda, örn. event id öğesinin "_handlerMap" öğesinde bulunup bulunmadığını veya işlenecek ana sınıfın dağıtıcıya iletilip geçirilmediğini belirtmek için 'dispatchEvent 'öğesinden bir' bool '. – dyp

0

Bunun hakkında ne düşünüyorsunuz?

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 
İlgili konular