2009-03-23 5 views
5

un code paraît ci-dessous:Est-il possible de créer un répartiteur d'appel de méthode en C++?

struct X { 
    void MethodX() { 
    ... 
    } 
}; 

struct Y { 
    void MethodY() { 
    ... 
    } 
}; 

void test() { 
    X x; 
    Y y; 
    Dispatcher d; 
    d.Register("x", x, &X::MethodX); 
    d.Register("y", y, &Y::MethodY); 
    d.Call("x"); 
    d.Call("y"); 
} 

La question est de savoir comment mettre en œuvre Dispatcher. Cela ne me dérange pas que X et Y puissent hériter de quelque chose, mais Dispatcher devrait autoriser d'autres clients (pas seulement X et Y). Et je voudrais éviter les pointeurs de void * si possible :)

+0

avez-vous un accès à la bibliothèque boost? –

+0

Pourriez-vous s'il vous plaît clarifier "Le problème est le type de structure de données gardant les pointeurs ou les foncteurs de la méthode." –

+0

J'essayais de l'implémenter avec le template std :: tr1 :: mem_fun. Mais le type de résultat avait à l'intérieur le type de paramètres. Donc je ne pouvais pas faire un vecteur hétérogène le contenant. –

Répondre

5

Jetez un oeil à boost::function, il le fait.

+0

Je ne résout pas le problème. Jetez un oeil à la question mise à jour. –

+0

Peut-être que c'est le cas. J'étudie :) –

1

J'ai une réponse similaire here, mais la réponse de Mykola est plus proche de ce dont vous avez besoin.

1

Jetez un oeil à cet article:

http://www.oopweb.com/CPP/Documents/FunctionPointers/Volume/CCPP/functor/functor.html

Il implémente un foncteur à base de modèle en C++. void * est utilisé sous les hottes, mais tout est sécurisé car il est entouré de fonctions de template qui créent et déplient le vide *. Cela rendrait la mise en œuvre facile. Il prend en charge une variété de styles d'appel que les pointeurs de méthode simple ne pas (par exemple, vous pouvez passer une fonction en retournant quelque chose comme un foncteur retournant void et il ignore automatiquement la valeur de retour)

2

Pour éviter l'utilisation de boost et mettre en œuvre le vôtre, vous pouvez jetez un oeil au livre http://en.wikipedia.org/wiki/Modern_C%2B%2B_Design

Il y a une bibliothèque Loki décrit dans le livre avec une bonne explication comment faire votre propre assez intelligent pour votre foncteur besoin.

class Dispather 
{ 
public: 
    typedef boost::function< void (void) > FunctionT; 

    void Register(const std::string& name, FunctionT function) 
    { 
     registered_[ name ] = function; 
    } 

    void Call(const std::string& name) 
    { 
     RegisterdFunctionsT::const_iterator it = 
      registered_.find(name); 

     if (it == registered_.end()) 
      throw std::logic_error("Function is not registered"); 

     (it->second)(); 
    } 

private: 
    typedef std::map< std::string, FunctionT > RegisterdFunctionsT; 
    RegisterdFunctionsT registered_; 

}; 

int main() 
{ 
    X x; 
    Y y; 

    Dispather d; 
    d.Register("x", boost::bind(&X::MethodX, &x)); 
    d.Register("y", boost::bind(&Y::MethodY, &y)); 

    d.Call("x"); 
    d.Call("y"); 

    return 0; 
} 
+0

Cela a l'air génial. Comment lance-t-il typeof (& X :: MethodX) dans FunctionT? Comment puis-je l'implémenter moi-même et éviter une utilisation accrue? –

+0

Pour éviter l'utilisation boost ... et vous utilisez ensuite boost :: function? –

Questions connexes