Newsgroup: it.comp.lang.c++
Titolo: Oggetti "globali"

Volevo parlare con voi di un problema che ho incontrato gia' un po' di
volte e per il quale non sono mai riuscito a trovare una soluzione che
mi piacesse.
Mettiamo di aver disegnato un'applicazione secondo le regole dell'OOP e
il programma strutturato correttamente in un certo numero di oggetti. A
questo punto nasce l'esigenza di avere un registro univoco (poniamo che
venga scritto su file) delle attivita' dell'applicazione e di eventuali
errori. Quali sono i metodi per creare questo "log" in modo che sia
condivisibile ed univoco per tutti gli oggetti, la sua implementazione
sia mascherata e consenta agli oggetti che lo utilizzano di essere
abbastanza svincolati da esso?  ovviamente con i dovuti compromessi...
grazie e ciao
merlinO
P.S.: soluzioni che non mi piacciono:
- funzione log() globale
- passaggio via paramentro del log ad ogni oggetto

Merlino ha scritto:

Nella classe base di una gerarchia puoi inserire la dichiarazione
   static <untipo> log;
Cosi' facendo tutte le istanze che derivano dalla classe base
condivideranno
l'unica la variabile log. Questa non e' una definizione, quindi dovrai
inserire all'
interno del programma:
  <untipo> ClasseBase::log = <valore>;
Ciao, Claudio.

abbastanza svincolati da esso?  ovviamente con i dovuti compromessi...
Un sistema comune e' questo:
class Log
{
  public:
    ...
    static void Out(const char *fmt,...);
    static Log *GetInstance();
    ...
};
Log *Log::GetInstance()
{
  static Log lg;
  return &lg;
}
void Log::Out(const char *fmt,...)
{
  Log *lg=GetInstance();
  //
  // Usa lg per accedere all'oggetto log
  //
  ...
}
In altre parole crei una funzione static che restituisce
l'indirizzo di una istanza dichiarata static nella funzione
stessa e quando ti serve l'istanza da usare chiami questa
funzione (la logica di creazione delle static garantisce
che ti verra' restituita sempre la stessa istanza).
La chiamata che effettua il logging potrebbe essere a sua
volta dichiarata static per comodita' d'uso... es:
   ...
   Log::Out("Sono stati salvati %i oggetti",num_oggetti);
HTH
Andrea
--
Andrea Griffini, Programmer
http://www.netservers.com/~agriff

   static <untipo> log;
Per quanto ne so questo sistema potrebbe creare problemi se
qualcuno degli oggetti usa log nel costruttore e viene
instanziato staticamente.
Es:
   class MyObj : public BaseObject
   {
     public:
       MyObj::MyObj()
       {
         log->Write("Creato MyObj");
       };
   };
   MyObj my_obj;
In questo caso non e' possibile avere garanzie che quando viene
eseguito il costruttore di my_obj il costruttore dell'oggetto
statico log sia gia' stato chiamato.
Inoltre obbligare tutti gli oggetti a essere discendenti
da una classe base e' gia' di suo qualcosa di discutibile.
Se la facility di logging non ha a che fare con gli
oggetti allora dovrebbe essere qualcosa che non tocca sotto
nessun punto di vista gli oggetti stessi; tanto meno le
relazioni di inheritance.
Personalmente trovo molto piu' adatto un approccio del tipo
   Log::Write("creato myobj");
che si poggi dietro le quinte su un singleton.


La soluzione che ho adottato, e che non mi convince pienamente e' di
avere una classe Log a ciascuna istanza della quale e' associato un file
di log, in modo da poter scrivere localmente:
Log pippo("Test.log");
e quindi usare pippo, che ha metodi per scrivere, per registrare
messaggi specifici. Ho poi una funzione globale log che al suo interno
contiene una istanza statica della classe Log e che puo' essere usata
come destinazione di default.
Piu' in generale questo e' un tipo di problema che mal si adatta ad un
approccio object oriented, perche' per sua natura non e' localizzato.
L'ambito che si occupa di questo tipo di problemi e' detto Aspect
oriented Programming, ma non ne so granche'.
Ciao,
Nicola