Stratos: Punto de Encuentro de Desarrolladores

¡Bienvenido a Stratos!

Acceder

Foros





Duda Sobre Singletons

Iniciado por AgeR, 28 de Octubre de 2003, 05:10:47 PM

« anterior - próximo »

AgeR

 Pues tengo una duda sobre el uso de los singletons.
Vamos a ver, por ejemplo tengo una clase para generar logs y la he hecho de tipo singleton.
Dentro de otra clase, por ejemplo la que me maneja los gráficos, tengo un miembro de tipo Log.
Lo normal sería para, por ejemplo, escribir algo en el log hacer lo siguiente :
Log->ObtenInstancia()->Escribir("loquesea");

Ahora bien, no sería más cómodo hacer al crear la clase que use el log lo siguiente?
Log = Log->ObtenInstancia();

Después para escribir...
Log->Escribir("loquesea");

De hecho lo estoy haciendo de esta última forma y parece funcionar bien, pero por si acaso...
Hay algo que me he pasado por alto? Puede surgir algún problema o es así como suele hacerse?
Hmmm no estoy muy seguro de haber pillado la utilidad y uso de los singletons  (nooo)

Gracias!
---
Vale, creo que acabo de pillar algo XD
Vamos, que no hace falta que meta ningún miembro de tipo Log, con hacer CLog::ObtenInstancia() funcionaría (siempre que incluya la cabecera donde está la clase declarada).
Parece que lo normal sería hacer un #define Log CLog::ObtenInstancia() para no poner todo el chorrotón cada vez que quiera usarlo. Estoy en lo cierto?  (uoh)

sés

 No sé, a mí me parece mejor tu forma. Yo siempre hago las cosas así.

El único problema podría ser que "ObtenInstancia()" hiciera algo más y pudiera dar punteros diferentes entre llamadas. Pero si esa clase es tuya, y sabes que no hace nada extraño, no le veo el problema.
Soy indeciso... ¿o no?

CoLSoN2

 que has creado un objeto de tipo Log? si es una clase singleton no deberias ni poder hacer eso.
de toda la vida se han usado singleton con constructor privado, para evitar eso.
¿qué como lo creas entonces?
pues tienes tu clase:

class A {
Singleton();
~Singleton();
public:
static A &getSingleton() {
          static A;
          return A;
}
[...]
};


y luego para usarlo pues

A::getSingleton().blabla(..);


si estoy metiendo la zarpa vilmente que alguien me corrija, pero creo que estoy en lo cierto
Manuel F. Lara
Descargar juegos indie  - blog sobre juegos indie y casual
El Desarrollo Personal.com  - blog sobre productividad, motivación y espíritu emprendedor

Zaelsius

 Creo que Ager quiso decir:

pLog = Log::ObtenInstancia();

Edit: Joer acabo de ver el edit de Ager XD

Yo me refería a que a veces hago cosas del estilo de:

FunciónDeNoSeQué()
{

Graphics* pGraphics = Graphics::GetInstance();

pGraphics->Noseque();
pGraphics->talycual();


}


Aunque nunca he comparado el código generado para los dos casos(el mio y el de Ager, entiéndase).. es probable que no sea más eficiente que llamar a GetInstance() cada vez, pero a nivel de código queda algo más limpio que una macro.

AgeR

 Hmmm a ver, dentro de una clase que vaya a usar el log creo :

CLog *Log;


Cuando inicializo la clase, no "creo" un nuevo objeto de la clase CLog, lo que hago es lo siguiente :

Log = Log->ObtenInstancia();


Aunque viéndolo así quizá ahora me parece más correcto usar :

Log = CLog::ObtenInstancia();


El constructor del log no lo toco para nada  :ph34r:
Pero como ya digo, no sé mucho del tema de singletons, de ahí el pedir ayuda.


Zaelsius

 A ver si nos sincronizamos XDDDD

Edit: Ager tio pon un "m_ " a las variables miembro que si no aquí nos vamos a volver locos XDDD.

5º o 6º reedit(he perdio la cuenta): Ya podias haber puesto "m_pLog" desde un principio, k de ahí a "Log" hay un buen trecho :rolleyes:

Reeeeedit:
El peligro de guardar un puntero permanente a una clase singleton, es que a priori desconocemos cuando será destruido el singleton.

Sí, ya sé que cada uno sabe perfectamente como va su propio engine y el orden de destrucción de sus instancias globales, pero eso disminuye la independencia de las partes del sistema, al tener que saber en qué orden se destruye cada componente del sistema. Bla bla.  

AgeR

Cita de: "ZaelSiuS"Edit: Ager tio pon un "m_ " a las variables miembro que si no aquí nos vamos a volver locos XDDD.

5º o 6º reedit(he perdio la cuenta): Ya podias haber puesto "m_pLog" desde un principio, k de ahí a "Log" hay un buen trecho :rolleyes:
:rolleyes: Estoooooo perdón, tengo todas las clases bien escritas menos la de log  (nooo) .

Bueno, entonces parece que

m_pLog = CLog::ObtenInstancia();


es lo correcto.

Hmmm bueno, en mi engine todos los singletons que tengo previsto usar se crean al crear el engine, y no se destruyen hasta que no se destruye el engine, así que con un poco de cuidado no debería haber problema. Pero bueno, obviamente no parece la mejor solución...

Gracias por las respuestas, parece que lo voy pillando  (uoh)  

tiutiu

 ZaelSius lo ha dicho to bien xD
La finalidad del singleton es evitar q no se haga mas d una instancia de una clase. Entonces puedes hacer lo q t de la gana mientras no instancies. Si tu clase se llama CLog, entonces tenemos lo siguiente:


CLog::GetInstance()->metodo();


CLog *pLog = CLog::GetInstance();
pLog->metodo();

Estos son los 2 usos posibles q le veo ahora, aunq variara segun implementes el singleton. El segundo no crea ninguna instancia, simplemente mete el puntero en una variable para no tener q escribir tanto codigo.

Para el logger casi q con la primera manera ya vale, yo la segunda la uso por ejemplo para cuando cargo mogollon d modelos o texturas.
b>:: Pandora's Box project ::
Notas e ideas sobre desarrollo de engines para juegos

NaiL

 Wenas.. mientras leia westros comentarios.. pense ke dada la naturaleza de un sigleton..
si quereis poner una referencia al singleton dentro de otra clase.. para mejorar la visivilidad del codigo
quizas seria mas acertado declararlo como

class X
{
public:
  const static CLog* pLog = CLog::GetInstance();
  ...
...
}


edit:
obiamente teniendo en cuenta ke la vida del sigleton cubre la vida de los  objetos de la clase X, en caso contrario seria mejor ke el codigo fura un poko mas "confuso".

Zaelsius

 Briconsejo: Si intentas compilar ese código, verás que no te deja.

Sólo se podría inicializar fuera de la declaración de clase, en el .cpp. Tipo:

const CLog* X::pLog = CLog::GetInstance();


Y como dices en el edit, tratándose de este caso particular(singletones), es muy difícil hacer que funcione sin saber el orden de construcción de los singletones..

AgeR

 Bueno, pues gracias a todos. Ya tengo los singletons funcionando a la perfección. El caso es que estoy terminando un motor 2D (por llamarlo de alguna manera...) y ya que lo tengo casi terminado me he planteado hacer un mínimo de documentación y sacarlo por si alguien quiere usarlo.
Pero... los singletons se llevan bien con las dll?
Explico : El "motor" está dividido en diversas partes, y todas ellas son singletons. Está la clase motor, y dentro de esta hay una para graficos (resolución, color de fondo, etc.), otra para recursos (sprites, sonidos...), otra para input...

Habrá problemas al crear y/o usar los singletons de este modo?
Convendría más crear una librería estática en vez de la dll en este caso?

De nuevo, gracias por todo!

NaiL

 
Citar
Sólo se podría inicializar fuera de la declaración de clase, en el .cpp. Tipo:

const CLog* X::pLog = CLog::GetInstance();


Estas seguro? justamente los const static solo se pueden inicializar en la clase.. pero weno no intente compilar nada parecido.

PD: si fuera const se inicializaria en el constructor. no?

Zaelsius

 Sí, estoy seguro  :P . Los únicos tipos que se pueden inicializar en la declaración de clase son los "const static integrales"(al menos en Visual Studio). Los tipos integrales son int, char, etc. Tampoco vale int*, p.ej.

NaiL

 ke kurioso.. weno weno tomo nota :P






Stratos es un servicio gratuito, cuyos costes se cubren en parte con la publicidad.
Por favor, desactiva el bloqueador de anuncios en esta web para ayudar a que siga adelante.
Muchísimas gracias.