Stratos: Punto de Encuentro de Desarrolladores

¡Bienvenido a Stratos!

Acceder

Foros





Conociendo De Qué Clase Es Una Instancia ( C++ )

Iniciado por CoLSoN2, 24 de Marzo de 2005, 01:56:29 PM

« anterior - próximo »

CoLSoN2

 ¿Cuál es la mejor forma de emular el operador 'instanceof' de Java? Es decir, saber si un objeto es de una clase o no. ¿Que cada clase tenga una máscara y la instancia tenga por ejemplo un campo long mClassMask:

Estudiante::mClassMask = ESTUDIANTE_MASK | PERSONA_MASK | COSA_MASK;

??

Eso estaría "bien", pero tiene dos pegas:

a) es un curre tener que hacer eso para caaada clase de la jerarquía.
B) preferiría usar el identificador de la clase directamente, o un string ("ClassName") en vez de un enum como el del ejemplo.

¿No conoceréis alguna máscara mágica o algo?

Quizá no del estilo INSTANCEOF(instancia,ClassName), pero quizá si algo como CLASS_ID(ClassName) dentro de la declaración de la clase, que cree un campo string className con el nombre de la clase, no se.

¿Alguna idea?
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

zupervaca

 tienes que crear una estructura de nodos (prueba a usar la mia, dibNode, esta mi web :D) que almacene por ejemplo el nombre de la clase en formato string

cada vez que llames a instanceof tendras que indicarle la clase de la que lo quieres saber, esta clase contendra el puntero a su nodo en la estructura de nodos descrita, despues seria obtener el padre de este nodo y ya lo tendrias, que quieres saber el padre de su padre, pues el hacer varias llamadas a instanceof con el valor devuelto o puedes indicar un flag con parametros en la funcion instanceof, eso ya a gusto del consumidor

como no se explicarme bien si tienes alguna duda preguntame

saludos

CoLSoN2

 Si eso está muy bien, pero cómo automatizo
1) que cada clase derivada de ObjetoBase o lo que sea, se añada correctamente a ese árbol
2) saber la clase final de la instancia en cuestión (puede ser una variable A* pero realmente ser un B*, si B deriva de A).
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

Pogacha

 enum {
tcTipo1,
tcTipo2,
tcTipo3
};


class CEstaClase : public CBase1, public CBase2
{
   const int MiTipo = tcTipoY;
 public:
   virtual bool EsUn(int Tipo) { return  MiTipo==Tipo || (CBase1*)this->EsUn(Tipo) || (CBase2*)this->EsUn(Tipo); }
};


No se me ocurre nada mejor que eso.

Actualmente no tengo nada tan complejo como para una automatización de esto ... incluso me sorprende o bien no entendi el problema ...
Saludos.

senior wapo

 ¿ Lo que buscas no es el RTTI de C++ ?
¿ typeinfo, dynamic cast y tal?

Pogacha

 Lo que yo escribi era suponiendo que quisiese escapar al RTTI ...

zupervaca

 Puede que como siempre alguien diga A y yo entienda B, como no estoy seguro de lo que quieres hacer te pongo un ejemplo de lo que creo que es:

class a{};
class b : public a{};
class c : public b{};

instaceof(a) es "";
instanceof(b) es "a";
instanceof(c) es "a";

classof(a) es "";
classof(b) es "a";
classof(c) es "b";

classid(a) = "a";
classid(b) = "b";
classid(c) = "c";

¿seria algo asi?

ethernet

Cita de: "senior wapo"¿ Lo que buscas no es el RTTI de C++ ?
¿ typeinfo, dynamic cast y tal?
seconded, dejémonos de reinventar la rueda XD

CoLSoN2

 No tengo ni idea de lo que es RTTI XD

Pero lo que busco, zupervaca, es algo tipo: bool isInstance(instancia, clase) ;

clase podría ser un id entero, un string, un identificador de clase.. lo que sea.ç

@pogacha: eso es lo que vengo haciendo ahora, pero es un coñazo tener que ir añadiendo ID's a cada clase.
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

ethernet

Cita de: "CoLSoN2"No tengo ni idea de lo que es RTTI XD

Pero lo que busco, zupervaca, es algo tipo: bool isInstance(instancia, clase) ;

clase podría ser un id entero, un string, un identificador de clase.. lo que sea.ç

@pogacha: eso es lo que vengo haciendo ahora, pero es un coñazo tener que ir añadiendo ID's a cada clase.
Run time type information. En resumen es una herramienta que te da C++ para saber el tipo de las instancias que tienes en tiempo de ejecución. Busca información  y te ahorrarás algún que otro disgusto.


zupervaca

 te paso un web en español sobre el tema http://www.zator.com/Cpp/E4_9_14.htm, a mi gusto no me gusta usar ciertas cosas del c++ por que mete codigo extra (aparte del que mete ya de por si el lenguaje, por eso el c siempre tendra un lugar en mi corazon   :P ) , pero si no quieres liarte mucho lo mejor es usar el typeid y asi automatizas todo

senior wapo

 Para que te hagas una idea, te explico como funciona en VC++

Cuando compilas con RTTI activado, se añade al ejecutable un montón de información sobre la jerarquia de objetos de tu código, y el ejecutable crece más que un flame "Windows versus Linux"  (twist)

Imagino que ya lo sabes, pero cuando creas un objeto de una clase, se guarda en memoria como una estructura con un primer campo oculto que es un puntero al array de punteros de funciones virtuales (vftable). Pues bien, si compilas con RTTI, se añade delante del bloque de memoria de la vftable un puntero a la información RTTI.

En tiempo de ejecución, cuando recibes un puntero a un objeto cualquiera y preguntas su tipo (con typeid), el motor RTTI de VC++ mira los 4 bytes anteriores a la vftable, ya que apuntan a una estructura que guarda el nombre de la clase, y de que otras clases deriva (esto último solamente si usas en algún momento el operador ya que abulta mucho el tamaño del código). Esta estructura es un objeto llamado type info.

Dos objetos de la misma clase siempre tendrán esa cabecera de la vftable apuntando al mismo sitio (mismo bloque type info).

A efectos practicos solo necesitas saber que hay una funcion llamada typeid() que le pasas como parámetro un puntero a algo, y te devuelve un identificador único que representa la clase concreta de ese objeto. En pseudocodigo:


class CMunicion { ....};
class CMunicionMisil : public CMunicion {... };
class CMunicionCartucho : public CMunicion {...};

void recogerMunicion( CMunicion *municion )
{
   if ( typeid( municion) == typeid( CMunicionMisil ) ) { playSound("power1.wav");    player.misiles += 10; }
  if ( typeid( municion ) == typeid( CMunicionCartucho ))  { playSound("power2.wav");    player.balas += 5; }
}


Recuerda que los punteros a clases han de ser a clases con al menos un miembro virtual, ya que el puntero al bloque RTTI se guarda delante de la vftable y si no hay miembros virtuales no hay vftable.

PD: La sintaxis estará mal ya que nunca uso RTTI y te lo he puesto de memoria.

CoLSoN2

 Ya lo he estado mirando y creo que dynamic_cast es lo que quiero (no typeid), pero creía que esto era parte de C++ (quiero decir que no era RTTI), como static_cast y demás ¿es cierto?

Tal como he visto, dynamic_cast(puntero) devuelve NULL si no puede castearlo, luego es exactamente lo que necesito (if (dynamic_cast...).)
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

Warchief

 No soy gurú de c++, así que a lo mejor lo que digo es un poco estúpido  ;), pero de java me suena lo de reflection (no sé de qué), y buscando c++ reflection vienen cosas como:

http://www.vollmann.com/en/pubs/meta/meta/meta.html

http://seal.web.cern.ch/seal/snapshot/work...reflection.html


El primer link parece interesante por cosas como:

This is what you already have. Then you need a different interface for a general search machine2, which must provide information like:

   * what is the actual class of the object
   * what attributes does that class have
   * what are the actual values of these attributes for the object.

This is a classic reflection interface that gives you information about the properties of classes and objects.


pero quizá es una solución parecida a lo que planteáis.

Siento no tener más tiempo para indagar. Yo tiro la piedra, a ver si le da a alguien ;)  (ole)

En cualquier caso, a la vista del último mensaje parece que está solucionado.






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.