2009-03-23 16 views
5

consideri un codice seguente:È possibile creare il metodo call dispatcher in 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 domanda è: come implementare Dispatcher. Non mi importa che X e Y possano ereditare da qualcosa, ma Dispatcher dovrebbe consentire ulteriori client (non solo X e Y). E vorrei evitare i puntatori * vuoti * se possibile :)

+0

hai un accesso alla libreria boost? –

+0

Potrebbe chiarire per favore "Il problema è il tipo di struttura dati che mantiene i puntatori o i funtori del metodo." –

+0

Stavo cercando di implementarlo con il modello std :: tr1 :: mem_fun. Ma il tipo di risultato era all'interno del tipo di parametri. Quindi non ho potuto creare un vettore eterogeneo che lo contenga. –

risposta

5

Dai uno sguardo allo boost::function, lo fa.

+0

Non risolvo il problema. Dai un'occhiata alla domanda aggiornata. –

+0

Forse sì. Sto indagando :) –

1

Ho una risposta simile here, ma la risposta di Mykola è più vicina a ciò di cui hai bisogno.

1

Date un'occhiata a questo articolo:

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

Esso implementa un funtore modello basato in C++. void * è usato sotto i cappucci, ma è completamente sicuro per il tipo perché è avvolto da funzioni di modello che creano e scartano il vuoto *. Renderebbe l'implementazione facile. Supporta una varietà di stili di chiamata che i semplici puntatori del metodo non consentono (ad esempio, è possibile passare una funzione restituendo qualcosa come un functor che restituisce nulla e ignora automaticamente il valore restituito)

2

Per evitare l'utilizzo eccessivo e implementare il proprio, è possibile date un'occhiata al libro http://en.wikipedia.org/wiki/Modern_C%2B%2B_Design

C'è una biblioteca Loki descritto nel libro con una buona spiegazione come rendere il proprio abbastanza intelligente per il vostro functor necessità.

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

Questo sembra fantastico. Come cast typeof (& X :: MethodX) in FunctionT? Come posso implementarlo da solo ed evitare l'uso di boost? –

+0

Per evitare l'aumento di utilizzo ... e quindi stai usando boost :: function? –

Problemi correlati