Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

When is (this != this) in C++?

I have a very strange question.

I have a class/function :

class MCBSystem {

    [...]

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

And I inherit it (multiply) in another class :

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

Now, if I call the "setCallBack" function :

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

then "menuBox" has a value say 0x06cf22b8 but inside "setCallBack", "this" is 0x06cf2370.

Can someone explain what on earth is going on?

[EDIT:] The true question is : if I need to store 'this' inside 'setCallBack', how can I check later that 'menuBox == this'?

Many thanks in advace!

like image 416
Bill Kotsias Avatar asked Jun 29 '10 11:06

Bill Kotsias


2 Answers

Yes, the this pointer has to be patched to allow for multiple inheritance polymorphism. As a zeroth-order approximation, an instance of a class C that inherits from A and B can be thought to include an instance of A followed by an instance of B. Now if you have a pointer to a C instance and convert that to an instance of B, the this pointer must be different because the B instance is located after the C instance in memory. See this paper for an in-depth discussion.

Little test program:

#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));
}
like image 132
Philipp Avatar answered Oct 14 '22 22:10

Philipp


Given any pointer to an object, it's value will be different based on whatever it is cast to.

Within a member function of MenuBox, this points to the MenuBox part of the object in question.

However, in setCallBack, it is being cast to a pointer to the Receiver part of the object.

To put it another way, this will always equal this, but for any pointer p static_cast<MenuBox>(p) will never equal static_cast<Receiver>(p).

like image 21
Paul Butcher Avatar answered Oct 14 '22 22:10

Paul Butcher