Jump to content

  • Log In with Google      Sign In   
  • Create Account


Weird C++ casting problem


Old topic!
Guest, the last post of this topic is over 60 days old and at this point you may not reply in this topic. If you wish to continue this conversation start a new topic.

  • You cannot reply to this topic
7 replies to this topic

#1 smitty1276   Members   -  Reputation: 560

Like
0Likes
Like

Posted 24 October 2010 - 02:34 PM

Can anyone shed any light on this? Here is an approximation of what I have:


class A {};
class B : public A {};
class Meh {};

class C : public B, Meh {};

Foo::Foo(A* a)
{
m_pAObject = a;
m_pCObject = reinterpret_cast<C*>(a);
}

void C::SomeMethod()
{
this->DoStuff(); // <-- "this" and m_pCObject above don't match
}





C::C is only invoked once, but when I examine these guys in debugger the pointer assigned to m_pCObject and the this pointer when tracing in C are two different things--specifically, m_pCObject is 64 greater than the this pointer inside of C methods. The objects methods are only invoked as an instance of C from other places, so it hasn't been an issue. I added some methods to C so that Foo could notify it of some state change, and it is behaving as though it is pointing to a different, uninitialized instance.

Is there some behavior around the casting here that I'm not aware of? (I'm not able to use dynamic_cast, but I know that the A object will always be a C object.)

Sponsor:

#2 Bearhugger   Members   -  Reputation: 551

Like
0Likes
Like

Posted 24 October 2010 - 03:06 PM

Unfortunately, you can't easily do reinterpret_cast or () casts with multiple inheritance. That is because of how the compiler organizes multiple-inheritance internally.

In single inheritance, if a class C inherits A, internally, you'll have A's members, followed by C's members. That way, you can cast A to C and the other way around and it's always the same pointer.

In multiple inheritance, it doesn't work that way. If a class C inherits A and B, the internal representation of C will be A's members followed by B and C. (Or B, A and C) If you cast C to A, it still works, but if you cast it to B, then the resulting pointer to B is different then the original C pointer because B's data starts after A.

#3 smitty1276   Members   -  Reputation: 560

Like
0Likes
Like

Posted 24 October 2010 - 03:09 PM

OK, this is what I was afraid of. So, without RTTI/dynamic_cast, this isn't something that is possible?

#4 smitty1276   Members   -  Reputation: 560

Like
0Likes
Like

Posted 24 October 2010 - 03:13 PM

Also, I just realized that the classes that are inherited (in my example, A, B, and Meh... and a third one I didn't use in my example) are all pure virtual interfaces. They have no data defined at all. Shouldn't it work in that case?

#5 ApochPiQ   Moderators   -  Reputation: 14666

Like
0Likes
Like

Posted 24 October 2010 - 03:18 PM

These FAQs should shed some light on what's going on here.

#6 Bearhugger   Members   -  Reputation: 551

Like
0Likes
Like

Posted 24 October 2010 - 03:25 PM

I'd add this as well. Explains that stuff, with graphics and illustrations.

Basically, it shouldn't work even with interfaces because you need the vtable for the interface. Try to see if it works if you have non-virtual methods in your interface.

#7 Ashkan   Members   -  Reputation: 450

Like
0Likes
Like

Posted 24 October 2010 - 03:27 PM

Generally speaking using reinterpret_cast and multiple inheritance is a recipe for disaster as reinterpret_cast simply changes the static type of the pointer without making the required adjustments to the pointer value - adjustments that are automatically taken care of by the compiler behind the scene when static_cast or dynamic_cast is used. Moreover, you cannot downcast a virtual base class pointer to a derived class pointer using static_cast. This is because the case may involve some pointer adjustment that depends on the dynamic type of the object pointed to. The solution is to use dynamic_cast, which performs the correct conversion by checking the real type of the object.

So long story short, with non-virtual multiple inheritance you can use static_cast to walk the tree, while with virtual inheritance, dynamic_cast is the only way. If you want to avoid dynamic_cast, stay away from virtual inheritance.

#8 smitty1276   Members   -  Reputation: 560

Like
0Likes
Like

Posted 24 October 2010 - 03:41 PM

OK, this makes sense. Bearhugger, that was a good link.

Thanks for the help, everyone.




Old topic!
Guest, the last post of this topic is over 60 days old and at this point you may not reply in this topic. If you wish to continue this conversation start a new topic.



PARTNERS