Jump to content
  • Advertisement
Sign in to follow this  
smitty1276

Weird C++ casting problem

This topic is 2975 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

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

Share this post


Link to post
Share on other sites
Advertisement
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.

Share this post


Link to post
Share on other sites
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?

Share this post


Link to post
Share on other sites
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.

Share this post


Link to post
Share on other sites
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.

Share this post


Link to post
Share on other sites
Sign in to follow this  

  • Advertisement
×

Important Information

By using GameDev.net, you agree to our community Guidelines, Terms of Use, and Privacy Policy.

GameDev.net is your game development community. Create an account for your GameDev Portfolio and participate in the largest developer community in the games industry.

Sign me up!