views:

379

answers:

2

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!

+17  A: 

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));
}
Philipp
Then, how can I check later that menuBox == this (the one stored inside 'setCallBack'..?
Bill Kotsias
I think it should work if you cast them to a common base class.
Philipp
Thanks for all the replies. I solved it by doing :((FANLib::MCBSystem*)menuBox) == this, and yes, it worked!
Bill Kotsias
Use a C++ cast, e.g. `static_cast` instead.
Philipp
@FredOverflow: This won't help.
sbi
In general, don't cast. Either the conversion is implicit and the comparison OK, or ambiguous and not OK.
MSalters
+1  A: 

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).

Paul Butcher