Newsgroup: it.comp.lang.c++
Titolo: Classi Derivate e conoscenza dei tipi

Salve a tutti,
avrei enormente bisogno si un consiglio:
Ho creato un piccolo editor di testo per file PHP in cui eseguo il parsing 
dei file per indicizzare tutte le classi, le funzioni, le variabili del 
codice PHP
Per il salvataggio di questi simboli ho creato una classe tipo questa:
class SymbolItem
{
    .....
    private:
        int type; // mi dice se è una funzione/classe o variabile PHP
};
Sto ottimizzando il codice e sinceramente vorrei eliminare quella variabile 
type dalla classe e magari utilizzare  le classi derivate per rendere più
elegante e flessibile il tutto, qundi vorrei ottenere qualcosa del tipo:
class SymbolFunction : public SymbolItem ...
class SymbolVar : public SymbolItem ...
In questo modo tramite le funzioni virtuali distinguere i comportamenti 
internamente invece che esternamente.
Tutte queste classi sono inserite all'interno di una classe collection:
class SymbolCollection
{
      ......
    private:
        std::vector<SymbolItem*> m_list;
}
Il grosso problema è che da un lato questa soluzione migliora molto 
l'impostazione del mio codice  nei punti di eleborazione dei vari simboli 
perchè mi evito degli if sul tipo molto fastidiosi
ma dall'altro lato in alcuni punti ho la neccessità di sapere il tipo di 
simbolo che sto trattanto....ad esempio:
Quando visualizzo i simboli all'utente ho un Tree grafico e vorrei che la 
visualizzazione dei simboli delle classi fosse diversa da quello dei simboli 
delle funzioni o delle variabili....quindi qui io devo sapere che tipo di 
oggetto sto trattando.
Ma come fare quando si hanno le classi derivate?
In alcuni sorgenti ho visto un if di questo tipo per differenziare i tipi:
if ( dynamic_cast<SymbolFunction*>(pItem) ) // Questa è una funzione
if ( dynamic_cast<SymbolVar *>(pItem) ) // Questa è una variabile
Ma non mi sembra molto efficiente, bhoo... son parecchi giorni che guardo in 
giro per trovare una soluzione ma non ne ho trovato nessuna che faccia al 
mio caso.....
Secondo voi in questi caso è meglio tenere una variabile che mi indica il 
tipo o esiste qualche soluzione per evitare questo?
Spero che la mia domanda non sia troppo banale....
Grazie a tutti
Gian

Mia opinione personale: enum.
Non vedo molto la necessita' di creare delle classi derivate solo per
sopperire alla mancanza di un intero. Secondo me e' molto piu' oneroso
da parte del compilatore gestire classi che non fare un if.
Non so, bisognerebbe vedere quanto c'e' nelle classi derivate... Bo', io
lascerei un intero per identificare.
-- 
Posted via Mailgate.ORG Server - 
http://www.Mailgate.ORG

 il tipo o esiste qualche soluzione per evitare questo?
La soluzione migliore è sfruttare i meccanismi del linguaggio.
Comunque, se proprio avessi necessità di conoscere il tipo di un oggetto
(tieni presente che generalmente è indice di cattiva programmazione),
potresti utilizzare typeid, un operatore (?) che torna un riferimento ad
un type_info, tramite il quale (con la funzione membro .name()) si può
ottenere il nome del tipo.
HTH
-- 
[ Andrea Spadaccini - a.k.a. Lupino/Lupin85 - Catania - ICQ#: 91528290 ]
[ GPG ID: 5D41ABF0 - key @ 
pgp.mit.edu
 - Slackware 10.1 w/Linux 2.4.22 ]
[ Linux User # 313388 - MAIL: a.spadaccini(at)catania(dot)linux(dot)it ]

 Ma come fare quando si hanno le classi derivate?
Un modo abbastanza comune per risolvere questo tipo di problema e'
questo:
class Visualizzatore;
class SymbolItem {
    public:
       ...
      // ogni sottoclasse puo' essere visualizzata in modi diversi
      virtual void show(Visualizzatore *v) const = 0;
};
class Visualizzatore {
  public:
     // definiamo una funzione per ogni classe concreta da visualizzare
     void showFunction(const SymbolFunction* f);
     void showVariable(const SymbolVariable* f);
     // esempio di utilizzo:
     void showCollection(const vector<SymbolItem *>& collection) {
         vector<SymbolItem *>::const_iterator it;
         for (it = collection.begin(); it != collection.end(); ++it) {
            // in questo momento non ci occorre sapere il tipo
            it->show( this );
         }
     }
};
class SymbolFunction: public SymbolItem {
   public:
     ...
     void show(Visualizzatore* v) const {
         v->showFunction( this );
     }
};
class SymbolVariable: public SymbolItem {
   public:
      ...
      void show(Visualizzatore* v) const {
          v->showVariable( this );
      }
};
Nota che anche Visualizzatore puo' essere una classe polimorfa, e
dichiari virtuali i metodi showFunction() e showVariable(), e fornmisci
differenti  implementazioni in questo caso avresti quello che si chiama
"Double Dispatching" che consente di far funzionare insieme due
gerarchie di classi pur mantenendole separate.
Spero di aver risposto al tuo quesito,
Fabio

 Spero di aver risposto al tuo quesito,
Alla grande....era proprio quello che stavo cercando, inoltre la stessa
soluzione mi serviva anche da altri parti.
In questo modo posso finalmente separare la visualizzazione dal tipo di
oggetti.
Non so come ringraziarti...
Ovviamente un grazie va anche a tutti gli altri che hanno risposto al
mio piccolo quesito.
Ciao