Newsgroup: it.comp.lang.c++
Titolo: Classe per FSM ed ereditarieta'

Salve a tutti,
quello che vorrei fare e' una gerarchia di FSM, cioe' una FSM base e
delle FSM derivate da base che processano gli stessi eventi, ma in
modo lievemente differente.  La FSM base definisce ovviamente
l'interfaccia, e anche l'implementazione standard, che le FSM derivate
possono usare/modificare/estendere.
Visto che tutte le FSM processano gli stessi eventi (supponiamo di
averli enumerati in un enum Event), pensavo di fare una cosa del
genere:
class FsmBase {
public:
  void feed(Event event) {
    switch(event) {
      case EVENT1: handleEvent1(); break;
      case EVENT2: handleEvent2(); break;
      ...
    }
  }
protected:
  virtual void handleEvent1() {
    switch(state) {
      case STATE1: handleEvent1State1(); break;
      case STATE2: handleEvent1State2(); break;
      ...
    }
  }
  virtual void handleEvent1State1() {
    ...
    state = newstate;
  }
  ...
private
  enum State {STATE1, STATE2, ..., NUMBER_OF_STATES};
  State state;
};
L'idea e':
* feed() e' pubblica non-virtual perche' tutte le FSM gestiranno gli
stessi eventi, non devono ridefinirla
* i gestori degli eventi (sia quelli cogli switch(state), sia i
gestori finali) sono protected virtual perche' le classi derivate
possono ridefinirli o estenderli (aggiungere stati, ridefinire
comportamento di un evento, eccetera)
* enum State: mi piacerebbe metterlo protected, in modo che tutte le
FSM derivate possano ereditarlo se vogliono, ma credo che sia molto
error-prone: ad es. se uno aggiungesse uno stato, ma non ridefinisse
NUMBER_OF_STATES, farebbe un casotto (lo erediterebbe dalal classe
base col valore sbagliato). In questo modo ogni FSM derivata dovra'
ridefinire l'enum (copia-incolla), non mi piace ma non ho ancora
trovato un'alternativa
Altre considerazioni:
* fare gli switch-dentro-switch non mi piace, ma in questo caso mi
sembra l'unico modo di far chiamare le funzioni virtuali giuste nelle
classi derivate; inoltre, nel mio caso particolare gli switch non sono
molto grandi (tipo 4--5 stati e una decina di eventi)
* l'overhead e' significativo: per ogni evento, per arrivare al
gestore vero e proprio ho tre chiamate di funzioni, di cui due
virtuali; anche questo non mi piace molto (specie visto che girera' su
un embedded), ma gli eventi sono cosi' radi (tipo 20 eventi al secondo
max) che non credo abbia alcun impatto sulle prestazioni
Che ne pensate?  Ogni suggerimento e' ben accetto :)
Pleg

 Pleg

 Forse no. Forse si. Forse non basta neppure, boh :-)
Eh eh :)
Rido perche' *prima* avevo scritto la mia FSM usando una... tabella di
puntatori a funzione :)
Ma poi non sono riuscito a trovare il modo di rendere la cosa
ereditabile dalle classi derivate, e quindi sono passato ad una
struttura a switch che chiamano metodi virtuali, che funziona
sicuramente.
Se ho una tabella di puntatori a funzioni membro, mi sa che la cosa
non funziona: le classi derivate erediterebbero questa tabella, che
punta ai metodi della classe base, e non credo di poter mischiare
puntatori alla classe base e alla classe derivata, perche' sono di due
tipi diversi.  Mi sa che dovrei riscrivere ogni volta la tabella, e
poi riscrivere gli handler nella classe derivata e fargli chiamare il
metodo corrispondente nella classe base... insomma, un casotto.
Pleg

Il 17/12/2010 19:26, Pleg ha scritto:

Non è una gran bella soluzione ..... perchè non la ripensi in funzione del 
pattern state ?
saluti.

 pattern state ?
Ad esempio?


http://en.wikipedia.org/wiki/State_pattern