2010-06-29 25 views
11

Tengo una pregunta muy extraña.¿Cuándo es (esto! = Esto) en C++?

tengo una clase/función:

class MCBSystem { 

    [...] 

    template <class Receiver> 
    void setCallBack(int i, Receiver* receiver, void(Receiver::*function)(void*)) { 
     iCallBacks.at(i) = new CallBack<Receiver>(receiver, function, this); 
    }; 
}; 

Y heredarlo (multiplicar) en otra clase:

class MenuBox : public OverlayBox, public HIDListener, public FANLib::MCBSystem { 
[...] 
}; 

Ahora, si llamo a la función "setCallback":

 menuBox->setCallBack(MenuBox::CLICKED, this, &SubMain::widgetClicked); 

luego "menuBox" tiene un valor de 0x06cf22b8 pero dentro de "setCallBack", "this" es 0x06cf2370.

¿Puede alguien explicar qué está pasando en la tierra?

[EDIT:] La verdadera pregunta es: si necesito almacenar 'esto' dentro de 'setCallBack', ¿cómo puedo verificar más tarde que 'menuBox == this'?

Muchas gracias en advace!

Respuesta

17

Sí, el puntero this tiene que parchearse para permitir el polimorfismo de herencia múltiple. Como una aproximación de orden cero, se puede pensar que una instancia de una clase C que hereda de A y B incluye una instancia de A seguida de una instancia de B. Ahora bien, si tiene un puntero a una instancia C y lo convierte en una instancia de B, el puntero this debe ser diferente porque la instancia B se encuentra después de la instancia C en la memoria. Ver this paper para una discusión en profundidad.

pequeño programa de prueba:

#include <iostream> 

struct A { int i; }; 
struct B { int j; }; 
struct C: A, B { }; 

#define PRINT(expr) std::cout << #expr " = " << expr << std::endl 

int main() { 
    C* c = new C; 
    B* b = c; 
    PRINT(b); 
    PRINT(c); 
    PRINT(static_cast<B*>(c)); 
} 
+1

Entonces, ¿cómo puedo verificar más tarde que menuBox == esto (el que está almacenado dentro de 'setCallBack' ...? –

+4

Creo que debería funcionar si los lanzas a una clase base común. – Philipp

+0

Gracias por todas las respuestas. lo resolvió haciendo: ((FANLib :: MCBSystem *) menuBox) == esto, y sí, funcionó! –

1

Dado cualquier puntero a un objeto, su valor será diferente en función de lo que se echa a.

Dentro de una función de miembro de MenuBox, this apunta a la parte MenuBox del objeto en cuestión.

Sin embargo, en setCallBack, se está convirtiendo en un puntero a la parte Receiver del objeto.

para decirlo de otra manera, this siempre será igual a this, sino para cualquier puntero pstatic_cast<MenuBox>(p) nunca será igual static_cast<Receiver>(p).