Newsgroup: it.comp.lang.c++
Titolo: Puntatore a funzione membro di una classe....

Salve a tutti!
Un anno fa proposi questo quesito, ed ora a distanza di un anno lo
vorrei riproporre.
Data una qualsiasi funzione membro f di una classe X
come ottengo un puntatore a X.f ?
Non prendetemi per pazzo, ma io non mi sono mai spiegato
questo, dato che tutti i S.O. chiedono puntatori a funzioni per
notificare segnali e/o eventi.
Chi programma in C++, come può risolvere questo inconveniente?
grazie per la cortese attenzione
cod

 notificare segnali e/o eventi.
Alt. Ferma il mondo.
La domanda era come fai a prendere l'indirizzo di un membro per poterlo
assegnare ad un puntatore. Ora tu stai parlando invece di puntatori a funzione.
Un metodo (ovvero una funzione membro) non e' una funzione. Anche se viene
chiamata "funzione membro" in realtà non e' una funzione. E' un metodo, appunto.
E' possibile prendere l'indirizzo di un metodo, ma non e' la stessa cosa di un
indirizzo di una funzione.
Se vieni dal C sai che esistono due tipi di puntaotori, in C. I puntatori a dati
e i puntatori a funzioni. In C++ ne esistono 4. I puntatori a dati, i puntatori
a funzioni, i puntatori a membri (dati) e i puntatori a metodi (membri
funzioni). E non sono affatto liberamente interscambiabili. Se il sistema
operativo si aspetta l'indirizzo di una funzione, non puoi passargli l'indirizzo
di un metodo piu' di quanto tu possa passargli l'indirizzo di una variabile.
Sono semplicemente cose diverse.
--
Andrea Ferro
---------
Brainbench C++ Master. Scored higher than 97% of previous takers
Scores: Overall 4.46, Conceptual 5.0, Problem-Solving 5.0
More info 
http://www.brainbench.com/transcript.jsp?pid=2522556

 notificare segnali e/o eventi.
In questo caso devi usare delle funzioni membro statiche (il cui puntatore è
equivalente a quello delle funzioni normali) che chiamino la tua funzione
membro. Vedi l'articolo di Pescio su thread e oggetti.
Daniele.


C'è un modo per ovviare a questo problema e passare quindi un puntatore
ad una funzione membro ad una funzione che accetta un puntatore a
funzione.
L'idea di base è:
template<class Obj, class Res, class Arg>
class unary_mem_fun_t
{
   public:
      typedef Obj object_type;
      typedef Res result_type;
      typedef Arg argument_type;
      typedef result_type (object_type::*mem_fun_type)(argument_type);
   private:
      // puntatore alla funzione membro di object_type
      mem_fun_type p_mem_fun;
      // puntatore ad una istanza di object_type
      object_type* p_obj;
   public:
      explicit unary_mem_fun_t(mem_fun_type m = 0, object_type* o = 0)
      : p_mem_fun(m), p_obj(o) {  }
      // applica la funzione membro
      result_type operator()(argument_type arg) const
      {
         return (p_obj->*p_mem_fun)(arg);
      }
      bool operator==(const unary_mem_fun_t&) const
      {
         return (p_obj == b.p_obj) && (p_mem_fun == b.p_mem_fun);
      }
};
// funzione helper
template<class Obj, class Res, class Arg>
inline unary_mem_fun_t<Obj, Res, Arg> unary_mem_fun(Res (Obj::*m)(Arg), Obj* o)
{
   return unary_mem_fun_t<Obj, Res, Arg>(m, o);
}
Quindi :
template<class Obj, class Res, class Arg>
class unary_fun_t
{
   public:
      typedef Obj object_type;
      typedef Res result_type;
      typedef Arg argument_type;
      typedef result_type (object_type::*mem_fun_type)(argument_type);
      typedef result_type (*fun_type)(argument_type);
   private:
      static unary_mem_fun_t<Obj, Res, Arg> instance;
      // funzione 'allocata'
      static result_type memory(argument_type arg)
      {
         static unary_mem_fun_t<Obj, Res, Arg> instance_ = instance;
         return instance_(arg);
      }
   public:
      unary_fun_t(mem_fun_type m, object_type* o)
      {
         instance = unary_mem_fun(m, o);
      }
      // restituisce la funzione associata
      operator fun_type() const { return &memory; }
};
// definizione membro statico
template<class Obj, class Res, class Arg>
unary_mem_fun_t<Obj, Res, Arg> unary_fun_t<Obj, Res, Arg>::instance;
// funzione helper
template<class Obj, class Res, class Arg>
unary_fun_t<Obj, Res, Arg> unary_fun(Res (Obj::*m)(Arg), Obj* o)
{
   return unary_fun_t<Obj, Res, Arg>(m, o);
}
Ecco un semplice esempio:
class foo
{
   private:
    int i;
   public:
      foo(int ii)
      : i(ii) {  }
      double f(double x) { return x * i; }
};
#include <iostream>
int main()
{
   typedef double (*pf_type)(double);
   foo o(2);
   pf_type pf = unary_fun(&foo::f, &o);
   std::cout << "pf = " << pf(2.2) << '\n';
}
Nota: è importante ricordare che pf_type DEVE avere C++ linkage altrimenti
ci sono problemi.
Questo approccio funziona solo per una funzione, ma è abbastanza semplice
generalizzare ad N funzioni, rendendo l'uso di unary_fun affidabile.
Basta costruirsi un "allocatore per funzioni".
Il codice non è piccolo, ma se interessa lo posso postare.
Saluti   Manlio Perillo