• Sábado 14 de Diciembre de 2024, 20:53

Autor Tema:  Puntero This  (Leído 1357 veces)

solarin

  • Miembro activo
  • **
  • Mensajes: 36
    • Ver Perfil
Puntero This
« en: Jueves 17 de Agosto de 2006, 15:24 »
0
en el proyecto en el que estoy trabajando todas mis clases derivan de una clase llamada "Notifier"

Notifier, tiene un metodo para enviar mensajes:
Código: Text
  1.  
  2. void NotifyWarningMessage(Notifier* noti, Message msg)
  3.  
  4.  

Como que todas las clases derivan de notifier, para llamar esta clase siempre me pasan el puntero "this"


Código: Text
  1.  
  2. //tengo que enviar un warning
  3.  
  4. NotifyWarningMessage(this,msg);
  5.  
  6. //donde msg ya esta creado anteriormente
  7.  
  8.  


La idea es escribir en el log que clase ha enviado el warning, pero si hago lo siguiente:

Código: Text
  1.  
  2. void NotifyWarningMessage(Notifier* noti, Message msg){
  3.  
  4.      invokerClass = typeid( noti ).name();
  5.  
  6. //loggear el warning...
  7. }
  8.  
  9.  
  10.  


invokerClass siempre es del tipo madre, es decir del tipo Notifier.

Hay alguna manera para que a partir del puntero this pueda tener el nombre de la clase hijo?

Es decir:

Si tengo declarada una clase asi:


public ClasseTest : public Notifier


Que invokerClass sea ClasseTest y no Notifier.


Gracias.

SteelX

  • Miembro MUY activo
  • ***
  • Mensajes: 218
    • Ver Perfil
Re: Puntero This
« Respuesta #1 en: Jueves 17 de Agosto de 2006, 16:31 »
0
Citar
El puntero this
Para cada objeto declarado de una clase se mantiene una copia de sus datos, pero
todos comparten la misma copia de las funciones de esa clase.
Esto ahorra memoria y hace que los programas ejecutables sean más compactos, pero
plantea un problema.
Cada función de una clase puede hacer referencia a los datos de un objeto,
modificarlos o leerlos, pero si sólo hay una copia de la función y varios objetos de esa
clase, ¿cómo hace la función para referirse a un dato de un objeto en concreto?
La respuesta es: usando el puntero this. Cada objeto tiene asociado un puntero a si
mismo que se puede usar para manejar sus miembros.


N.A: Salvador Pozo Coronado, Curso de C++
Inside the code

solarin

  • Miembro activo
  • **
  • Mensajes: 36
    • Ver Perfil
Re: Puntero This
« Respuesta #2 en: Jueves 17 de Agosto de 2006, 16:44 »
0
Buena info del puntero this.. pero como solventar el problema con la herencia? <_<

rbarreon

  • Nuevo Miembro
  • *
  • Mensajes: 2
    • Ver Perfil
Re: Puntero This
« Respuesta #3 en: Lunes 28 de Agosto de 2006, 02:05 »
0
Hola solarin.

Eso es debido a que en la función trabajas con las clases hijas a través de un puntero de tipo clase padre.

Si el número de clases que heredan de Notifier no es muy elevado puedes utilizar typeid o dynamic_cast para saber el nombre de la clase hija, utilizandolo de la siguiente manera:

void NotifyWarningMessage(Notifier* noti, Message msg){

    if(typeid(*noti) == typeid(ClaseQueHeredaDeNotifier1)){
         cout << "La clase es de tipo ClaseQueHeredaDeNotifier1" << endl;
    }
    if(typeid(*noti) == typeid(ClaseQueHeredaDeNotifier2)){
         cout << "La clase es de tipo ClaseQueHeredaDeNotifier2" << endl;
    }
    if(typeid(*noti) == typeid(ClaseQueHeredaDeNotifier3)){
         cout << "La clase es de tipo ClaseQueHeredaDeNotifier3" << endl;
    }
   
    ... //Así sucesivamente con todas las clases que heredan de Notifier

}

La otra opción es utilizar dynamic_cast<> de la misma forma. Este operador sirve para hacer casting dinámico, es decir, tienes una clase padre, y de ella heredan varias clases hijas (como en tu caso), pues si instancias varias clases hijas utilizando para ello un puntero de la clase padre, con dynamic_cast puedes transformar ese objeto a un objeto manejado a través de un puntero de la clase hija a la que pertenece. Es algo engorroso, aquí un ejemplo para aclarar:

//Punteros de la clase padre
Notifier* x;
Notifier* y;

/* Instanciamos objetos de tipo "clases que heredan de notifier" con punteros de la clase padre */
x = new ClaseQueHeredaDeNotifier1();
y = new ClaseQueHeredaDeNotifier2();

//Ahora ponemos ejemplos de cuando se puede llevar a cabo el casting dinámico

/* Este casting es posible ya que en x hay instanciado un objeto de tipo ClaseQueHeredaDeNotifier1 */

ClaseQueHeredaDeNotifier1* c;
c = dynamic_cast<ClaseQueHeredaDeNotifier *>(x);

/* Este casting no es posible ya que en y el objeto que hay instanciado no es de tipo ClaseQueHeredaDeNotifier1 */

ClaseQueHeredaDeNotifier1* v;
v = dynamic_cast<ClaseQueHeredaDeNotifier1 *>(y);

NOTA: Cuando dynamic_cast<> se lleva a cabo satisfactoriamente devuelve un puntero hacia el objeto ya convertido a la clase deseada. Cuando falla devuelve 0.

Bien, pues para saber el nombre de la clase hija lo utilizamos de la siguiente manera:

void NotifyWarningMessage(Notifier* noti, Message msg){

    ClaseQueHeredaDeNotifier1* x;
    if(x = dynamic_cast<ClaseQueHeredaDeNotifier1*>(noti)){
         cout << "ClaseQueHeredaDeNotifer1" << endl;
    }

    ClaseQueHeredaDeNotifier2* y;
    if(y = dynamic_cast<ClaseQueHeredaDeNotifier2*>(noti)){
         cout << "ClaseQueHeredaDeNotifer2" << endl;
    }

    ... //Así sucesivamente con todas las clases que heredan de Notifier

}

En fin, espero que te sea de utilidad.
Saludos.

solarin

  • Miembro activo
  • **
  • Mensajes: 36
    • Ver Perfil
Re: Puntero This
« Respuesta #4 en: Lunes 28 de Agosto de 2006, 10:31 »
0
Gracias por la respuesta, pero el numero de clases hijas es realmente muy alto. Al final he encontrado la solucion en la docu de msdn.

Código: Text
  1.  
  2. // expre_typeid_Operator.cpp
  3. // compile with: /GR /EHsc
  4. #include &#60;iostream&#62;
  5. #include &#60;typeinfo.h&#62;
  6.  
  7. class Base {
  8. public:
  9.    virtual void vvfunc() {}
  10. };
  11.  
  12. class Derived : public Base {};
  13.  
  14. using namespace std;
  15. int main()
  16. {
  17.    Derived* pd = new Derived;
  18.    Base* pb = pd;
  19.    cout &#60;&#60; typeid( pb ).name() &#60;&#60; endl;   //prints &#34;class Base *&#34;
  20.    cout &#60;&#60; typeid( *pb ).name() &#60;&#60; endl;   //prints &#34;class Derived&#34;
  21.    cout &#60;&#60; typeid( pd ).name() &#60;&#60; endl;   //prints &#34;class Derived *&#34;
  22.    cout &#60;&#60; typeid( *pd ).name() &#60;&#60; endl;   //prints &#34;class Derived&#34;
  23.    delete pd;
  24. }
  25.  
  26.  
  27.  


importante es declarar una funcion virtual en la clase padre i usar la opcion /GR para el compilador.

Gracias por la ayuda igualmente.