Newsgroup: it.comp.lang.c++
Titolo: Singleton

Salve,
questo sorgente dovrebbe permettere una sola istanza di una classe... ma:
#include <iostream>
class Singleton {
 Singleton() { } // il costruttore è privato!
 public:
  static Singleton& Get() {
   static Singleton s; // dato che è statico verrà creato UNA sola volta
  return s;
  }
 int x; // un membro pubblico per evitare di scrivere metodi di accesso
};
Singleton obj1 = Singleton::Get();
Singleton obj2 = Singleton::Get();
int main () {
 obj1.x = 1;
 obj2.x = 2;
 std::cout << obj1.x << std::endl;
 std::cout << obj2.x << std::endl;
 return 0;
}
Stampa 1 e 2. Cioè, a me sembra che le istanza siano 2 e distinte.
Chiarimenti?
Grazie
--
Luigi
--
void f (OS x) {while (x.getbugs() > 0); destroy(earth);};
f (windows); // Meno male!

 ha scritto nel messaggio
news:T_tc9.136121$n04.3...@twister2.libero.it...

Dovresti lavorare coi puntatori :
 class Singleton {
  Singleton() { } // il costruttore è privato!
  public:
   static Singleton& Get() {
    static Singleton s; // dato che è statico verrà creato UNA sola volta
   return s;
   }
  int x; // un membro pubblico per evitare di scrivere metodi di accesso
 };
 Singleton *obj1 = &Singleton::Get();
 Singleton *obj2 = &Singleton::Get();
 int main () {
  obj1->x = 1;
  obj2->x = 2;
  std::cout << obj1->x << std::endl;
  std::cout << obj2->x << std::endl;
  return 0;
 }
Oppure se non vuoi utilizzare l'operatore ->   :
/*
            ...
*/
Singleton& obj1 = Singleton::Get();
Singleton& obj2 = Singleton::Get();
 int main () {
  obj1.x = 1;
  obj2.x = 2;
  std::cout << obj1.x << std::endl;
  std::cout << obj2.x << std::endl;
  return 0;
 }
In questo modo funziona :P
Il motivo per cui non funziona nel tuo caso e' dato dal fatto che quando fai
Get anche se Get ritorna un oggetto per referenza(quindi l'oggetto non viene
copiato) quando questo viene assegnato a obj1 viene creata una copia dal
compilatore, stessa cosa accade per obj2.

Si, con i puntatori e i riferimenti funziona, ma se io ho una classe
implementata con il pattern Singleton per evitare di fornire più di
un'istanza... basta crearsi oggetti comuni e si aggira l'ostacolo, no?
Ciao


 ha scritto nel messaggio
news:dquc9.136244$n04.3...@twister2.libero.it...

Non capisco che cosa intendi per : "basta crearsi oggetti comuni e si aggira
l'ostacolo"
Luca

 un'istanza... basta crearsi oggetti comuni e si aggira l'ostacolo, no?
	Dovresti provare a implementare il singleton con i puntatori. Da Design
Patterns:
class Singleton
{
public:
	static Singleton* Get()
	{
		if( _instance == 0 )
			_instance = new Singleton;
		return _instance;
	}
private:
	Singleton();
	static Singleton* _instance;
};
Singleton* Singleton::_instance = 0;
	Dopo che e' stata creata un'instanza la condizione dell'if non sara'
mai piu' vera. Magari per maggiore sicurezza bisognerebbe inibire anche il
costruttore di copia...
_dave_

 ha scritto nel messaggio
news:20020901222553.65e...@tin.it...

Secondo me anche se la prima istanza la crea static va bene, pero' per i
vari riferimenti deve usare o i puntatori o le reference.

 l'ostacolo"
Se io implemento una classe, seguendo quel pattern, significa che l'utente
della mia classe, non deve avere più di un'istanza di quella classe. Ma
invece, basta crearsi oggetti comuni (cioè non puntatori o riferimenti a
oggetti, ma istanze effettive) per avere tutte le istanza che voglio, e
violare le regole imposte dal pattern.


> Dovresti provare a implementare il singleton con i puntatori.
Si, ok. Il punto è che su internet ho trovato il sorgente che poi ho postato
qui. E volevo far notare che il pattern esposto come adatto a permettere una
sola istanza, in realtà offre un modo per avere tutte le istanze che si
desiderano. La soluzione può essere implementare il pattern con i puntatori,
come dici tu.


 istanza che voglio, e violare le regole imposte dal pattern.
	Se inibisci il costruttore di copia, una violazione del pattern
mediante "oggetti comuni" non verrebbe neanche compilata.
_dave_

Ho scritto questo:
class Singleton {
 public:
 static Singleton* Get() {
  if (instance == 0)
   instance = new Singleton;
  return instance;
 }
 int x;
 private:
 Singleton();
 static Singleton* instance;
};
Singleton* obj1 = Singleton::Get();
int main () {
 obj1->x = 1;
 std::cout << obj1->x << std::endl;
 return 0;
}
Ma il linker di gpp mi da questo errore:
c:/djgpp/tmp\ccVeUJiO.o(.text+0x7d):Singlepub.cpp: undefined reference to
`Singleton::instance'
c:/djgpp/tmp\ccVeUJiO.o(.text+0x9e):Singlepub.cpp: undefined reference to
`Singleton::Singleton(void)'
c:/djgpp/tmp\ccVeUJiO.o(.text+0xac):Singlepub.cpp: undefined reference to
`Singleton::instance'
c:/djgpp/tmp\ccVeUJiO.o(.text+0xd2):Singlepub.cpp: undefined reference to
`Singleton::instance'
inoltre se modifico il sorgente aggiungendo questa riga
Singleton* obj2 = Singleton::Get();
Compila comunque, ma il linker da lo stesso errore.


 to`Singleton::Singleton(void)'
	Definisci il costruttore da qualche parte oppure sostituisci il punto e
virgola con {} (all'interno della dichiarazione della classe).
_dave_

 un'istanza... basta crearsi oggetti comuni e si aggira l'ostacolo, no?
Questo perchè la classe in questione è dotata di un costruttore copia
pubblicamente accessibile (che è sintetizzato dal compilatore). Dichiara il
costruttore copia come privato e nessuno potrà copiare l'oggetto.
Max

Ah, ecco. Pensavo che avessi messo tu {}, non ci ho fatto caso che c'era il
punto e virgola :)
Cmq, basta rendere privato anche il costruttore per copia, e il pattern che
ho postato, permette un'unica istanza.
Ciao
