Newsgroup: it.comp.lang.c++
Titolo: Classe tuttofare

E' possibile creare una classe che abbia una funzione ridefinibile ad ogni
oggetto creato?
Per esempio:
class Generic {
Action(){ //Nothing }
};
Generic A;
Generic B;
A.Action // Visualizza un messaggio
B.Action // Cancella lo schermo, etc...
Una cosa simile l'ho ottenuta definendo Action virtuale e poi creando le
classi A e B ereditando da Generic così da poter ridefinire Action come mi
pare, però in questo modo devo creare nuovi tipi di oggetti solo per
ridefinire una funzione (e solo il corpo, poichè i parametri passati
sarebbero uguali). Mi chiedevo se ci fossero dei trucchi per aggirare il
problema, cioè, non dover creare una classe per ogni oggetto che mi serve,
ad esempio, nella programmazione Windows, se creo la classe Pulsante, la
funzione OnCLick() sarà del tutto generica, ogni oggetto farà cose diverse.
Spero ci sia qualcuno che ha la pazienza di illuminare un principiante.
Grazie.

 B.Action // Cancella lo schermo, etc...
Potresti fare con puntatori a funzione (ma le funzioni dovrebbero avere
tutte
la stessa interfaccia).
Potresti fare con la tecnica delle Policy e template:
template < class T >
class Generic {
    Action() { T::action(); }
};
In questo modo devi fare anche qui una classe per ogni funzione (in realta'
basta una struct per ogni funzione)
ex:
struct CancellaSchermo {
    void static action() { //cancella schermo }
};
e poi:
    Generic<CancellaSchermo> miaGeneric;
     miaGeneric.Action();
non mi vengono in mente altri modi semplici.
Putroppo ne C++ ne Java hanno il concetto di Delegate ( lo ha solo il C# )
che in questo caso ti avrebbe proprio fatto comodo.
-- 
Posted from [194.214.173.28] 
via Mailgate.ORG Server - 
http://www.Mailgate.ORG

Nella classe generic metti anche un enum che definisce la "funzionalità"
dell'oggetto che deve essere usata. Poi, in Generic::Action, un super switch
:-)
--
Stefano Pettini
Notary of 
www.thawte.com

 Grazie.
Mi chiedevo: se tu fai una cosa di questo genere
class Generic;
typedef bool(*action)(Generic&);
class Generic
{
public:
      Generic(action a=NULL):m_action(a){}
      ~virtual Generic(){};
      bool Action(){return action(*this);}
private:
      action m_action;
}
a questo punto potresti fare:
bool action1(Generic& btn1)
{
 ... do something
}
bool action2(Generic& btn2)
{
 ... do sumthing else
}
int main()
{
   Generic gen1=new Generic(action1);
   Generic gen2=new Generic(action2);
   gen1->Action(); //chiama bool action1(Generic& gen1) ?
   gen2->Action(); //chiama bool action2(Generic& gen2) ?
}
Tenete conto che ora non ho un compilatore, per cui non sono in grado
di provare se l'idea funziona o meno - ma in linea di massima
dovrebbe... L'unico problema č che le funzioni non possono accedere ai
membri protetti o privati delle classi.
Sennň puoi mettere in piedi una soluzione da delegation-model di java
- si tratta sempre di scrivere una classe per ogni azione differente
che tu vuoi, ma non č poi cosě differente dallo scrivere una funzione:
class IAction
{
public:
      virtual Action()=0;
}
class Generic
{
public:
      Generic(){...}
      virtual ~Generic(){...}
      public AddListener(Action* action)
      {
         m_list.push_back(action);
      }
      public Action()
      {
         for(list<Action*>::iterator
it=m_list.begin();it!=m_list.end();++it)
              it->Action();
      }
private:
      list<Action*> m_list;
}
 
Si tratterŕ di buttare giů una classe concreta basata su IAction per
ogni comportamento diverso, e di "registrarla" usando AddListener
(ovvio, avrei dovuto implementare anche RemoveListener, ma non mi
viene in mente come farlo con una lista di STL, a meno di iterarla e
cercare it=IAction* da rimuovere...)
Saluti.
Zello

 ha scritto nel messaggio
news:9jrpru$1bd0n$1...@ID-85396.news.dfncis.de...

Veramente non mi ricordo bene cosa fa enum, quindi approfondirò, comunque
non sarebbe adatto allo scopo perchè non posso prevedere a priori tutti gli
usi per una funzione generica tipo Pulsante.Premi(). La mia idea era quella
di creare un header contenente gli oggetti generici, tipo Class Pulsante, e
poi nel codice creare quanti oggetti mi servivano e riscrivere solo la parte
della funzione generica.


Grazie, mi risparmia giŕ un passaggio, cioč l'ereditare una classe per ogni
oggetto.

Poichè le funzioni non possono essere definite a runtime (le devi scrivere tu
e poi compilarle), questo contrasta con il fatto che, dici, non puoi prevedere
a priori tutte le funzionalità. Dovrai scrivere da qualche parte il codice,
no? Fai tante funzioni private, poi metti uno switch che si basa su un enum
(ovvero su un intero) che capisce a runtime quale chiamare.


mi sembra ci sia un baco:
Action() { /* Nothing */}
casomai ...
E guarda che in window di solito erediti da Button


 (ovvero su un intero) che capisce a runtime quale chiamare.
Cosi' facendo pero' dovrebbe modificare il codice dello switch ogni
volta che aggiunge una nuova funzione.
Con metodi virtual o template la cosa e' piu' elegante e generica... o
sbaglio?
Ciao.

Si, in questo caso dovrebbe modificare lo switch ogni volta. La soluzione non
è elegante, ma funziona.
