2010-02-06 9 views
2

Je travaille donc sur cette classe de gestion d'événements. Je stocke une liste de pointeurs vers les fonctions membres de la signature void (Event*) où Event est juste une structure qui stocke des données aléatoires pour le moment.Membre Fonction Pointeur avec argument de classe de base acceptant l'argument de classe dérivée

typedef boost::function<void(Event*)> Callback; 
typedef vector<Callback> CallbackList; 

class EventManager 
{ 
public: 
    template<typename T> 
    void RegisterEventHandler(const std::string& type, void (T::*handler)(Event*), T* obj) 
    { 
     mCallbackList[type].push_back(boost::bind(handler, obj, _1)); 
    } 

    void DispatchEvent(const std::string& type, Event* evt) 
    { 
     for(CallbackList::iterator it = mCallbackList[type].begin(); it != mCallbackList[type].end(); ++it) 
     { 
     Callback callback = (*it); 
     callback(evt); 
     } 
    } 
private: 
    hash_map<std::string, CallbackList> mCallbackList; 
}; 

Je me demande s'il est possible pour moi de tirer différentes versions de l'événement, et passer des pointeurs vers les fonctions membres dans cette catégorie? Actuellement j'essaye ceci.

class MouseEvent : public Event 
{ 
public: 
    int testMouseData1; 
    int testMouseData2; 
    int testMouseData3; 
}; 

class HelloWorld 
{ 
public: 
    void Display(MouseEvent* evt) 
    { 
     cout << "Hello, world!" << endl; 
    } 
}; 


int main(void) 
{ 
    MouseEvent* evt = new MouseEvent(); 

    HelloWorld* world = new HelloWorld(); 
    eventManager->RegisterEventHandler("testType", &HelloWorld::Display, world); 

    return 0; 
} 

Cela me donne l'erreur suivante dans XCode. Savez-vous comment transmettre en toute sécurité un pointeur qui attend une classe dérivée dans sa signature de fonction? Merci.

Répondre

2

J'ai donc trouvé une solution qui semble fonctionner pour moi, mais je ne suis pas sûr que ce soit entièrement sécuritaire. J'ai changé la méthode de RegisterEventHandler pour lancer tous les pointeurs de fonction que j'envoie dans le même type ...

template<typename T1, typename T2> 
    void RegisterEventHandler(const String& type, T1 handler, T2* obj) 
    { 
     void (T2::*evtHandler)(Event*) = (void (T2::*)(Event*)) (handler); 
     mCallbackList[type].push_back(boost::bind(evtHandler, obj, _1)); 
    } 

tout semble maintenant travailler comme je l'ai prévu à l'origine. Mais je suis assez nouveau à tout cela, donc je ne suis pas tout à fait sûr si c'est une chose sûre à faire. Des pensées? Merci

1

Si votre prototype attend le type "Evénement", vous devez vous assurer que la fonction void Display(MouseEvent* evt) accepte le type "Event". Donc, changez-le en void Display(Event *evt) Ensuite, à l'intérieur de l'appel, vous pouvez le repasser à MouseEvent, en supposant que l'appelant a passé un vrai MouseEvent, référencé comme un "Event".

Deuxièmement, je crois que vous pouvez avoir d'autres problèmes avec la façon dont vous appelez RegisterEventHandler car il est dans un modèle mais vous ne spécifiez pas le type de modèle.

+0

@Harley - Les fonctions modèle ont inférence de type, donc je dirais que la façon dont il appelle RegisterEventHandler est paramètres OK de modèle de fonction – Manuel

+0

peuvent être déduites des arguments de la fonction, néanmoins spécifiant explicitement le type de modèle aiderait op déterminer pourquoi instanciation n'a – Anycorn

+0

Convenu , essayant juste d'éliminer toutes les variables ici. Assez sûr que le point principal @Morgan doit regarder ici est le type "Event" vs "MouseEvent". –

Questions connexes