Newsgroup: it.comp.lang.c++
Titolo: puntatore statico ad un metodo statico di una classe

Salve gente,
sto cercando di ottimizzare una classe (che esegue del codice a seconda di una certa condizione) usando i puntatori a membro, senza bisogno di 'if'. Semplificando è qualcosa del tipo
[code]
class dynamic_flagged {
  public:
    void set_flag(bool flag){
      if (flag)
        to_do = &dynamic_flagged::do_this;
      else
        to_do = &dynamic_flagged::do_that;
    }
    bool do_it() {
      return (this ->* to_do)();
    }
  private:
    bool (dynamic_flagged::*to_do)();
    bool do_this() {
      return true;
    }
    bool do_that() {
      return false;
    }
};
[/code]
così una volta impostato il flag tramite apposito metodo 'set_flag' tutte le chiamate a 'do_it' non devono passare per un 'if'.
Ad es.
[code]
  dynamic_flagged df;
  df.set_flag(true);
  bool retval;
  retval = df.do_it();
[/code]
Il problema è quando cerco di trasformare tutti i metodi della classe in metodi statici
[code]
class static_flagged {
  public:
    static void set_flag(bool flag){
      if (flag)
        to_do = &do_this;    //(*)
      else
        to_do = &do_that;    //(*)
    }
    static bool do_it() {
      return (*to_do)();    //(*)
    }
  private:
    static_flagged();
    static bool (*to_do)();
    static bool do_this() {
      return true;
    }
    static bool do_that() {
      return false;
    }
};
[/code]
così da fare
[code]
static_flagged::set_flag(true);
static_flagged::do_it();
[/code]
compilando ottengo
da Visual Studio 2005
error LNK2001: unresolved external symbol "public: static bool (__cdecl* static_flagged::to_do)(void)" (?to_do@static_flagged@@2P6A_NXZA) tmp.obj
e da MinGW
(.text$_ZN14static_flagged5do_itEv[static_flagged::do_it()]+0x7): undefined reference to `static_flagged::to_do'[/code]
i problemi spariscono se commento le righe contrassegnate con (*);
qcuno mi sa spiegare?
Volendo poi inizializzare il valore statico 'to_do' affinché punti a 'do_this' che sintassi devo usare?
Se uso
[code]
bool (static_flagged::*to_do)() = &static_flagged::do_this();
[/code]
il compilatore si oppone perché 'do_this' è private.

 il compilatore si oppone perché 'do_this' è private.
Non capisco il ragionamento che fa il compilatore, ma l'istruzione per 
inizializzare la variabile membro e' la seguente:
bool (*static_flagged::to_do)() = &static_flagged::do_this;
-- 
     Carlo Milanesi
 
http://digilander.libero.it/carlmila

 sto cercando di ottimizzare una classe (che esegue del codice a seconda di una certa condizione) usando i puntatori a membro, senza bisogno di 'if'. Semplificando � qualcosa del tipo
Non darei per scontato che la risoluzione dei puntatori a membro sia
sempre e comunque piu' efficiente di un condizionale, senza contare
che il modo naturale di fattorizzare questo tipo di situazioni e'
definire una classe base con funzioni membro virtuali pure ed
un'implementazione concreta per ciascun caso. In questo modo l'unico
condizionale da gestire esplicitamente e' la scelta di quale
sottoclasse utilizzare.
Ciao,
Nicola

 bool (*static_flagged::to_do)() = &static_flagged::do_this;
giustissimo, grazie 1000!

 sottoclasse utilizzare.
Se ho ben capito quello che intendi ogni chiamata a 'do_it' passerebbe da un if
per stabilire se usare la classe che implementa il codice contenuto in 'do_this'
oppure quella che implementa il codice di 'do_that'.
Un'unica classe con
[code]
bool do_it(){
  if(flag)
    return do_this();
  else
    return do_that();
}
[/code]
non sarebbe la stessa cosa?


Assolutamente no! io dico una cosa tipo:
class action {
  public:
    virtual bool do() = 0;
};
class this_action : public action {
  bool do() { return true; }
};
class that_action : public action {
  bool do() { return false; }
};
bool do_it(action * a) {
  return a->do();
}
action * a = flag ? new this_action : new that_action;
do_it(a);
Ciao,
Nicola

 
Scusami ma forse non mi sono spiegato bene, io voglio evitare che ogni chiamata
a 'do_it' passi per un if (o operatore ternario) in quanto il flag cambia
'raramente' rispetto alle chiamate al metodo.
Usando i puntatori a metodo mi e' sufficiente impostare il puntatore al metodo
giusto ogni volta che il flag cambia.
Sicuramente la soluzione con il metodo virtuale puro sarebbe piu' efficiente in
caso di flag che cambia 'spesso'.
In ogni caso ogni ulteriore commento e' sempre ben accetto.
Grazie.


Non hai letto il mio esempio con sufficiente attenzione. Una volta
inizializzato a, do_it() puo' essere chiamato tutte le volte che vuoi
senza passare per alcun if o operatore ternario. Ad es.:
for ( int i = 0; i != 100; ++i )
{
  action * a = i % 2 == 0 ? new this_action : new that_action;
  for ( int j = 0; j != 1000; ++j )
    do_it(a);
}
Per ogni cambiamento della condizione do_it() e' chiamata mille volte.
Ciao,
Nicola

Nicola Musatti ha scritto:

Ok ora e' piu' chiaro, grazie 1000.