Not logged in, Join Here! or Log In Below:  
 
News Articles Search    
 

 Home / General Programming / Cross-casting? Account Manager
 
Archive Notice: This thread is old and no longer active. It is here for reference purposes. This thread was created on an older version of the flipcode forums, before the site closed in 2005. Please keep that in mind as you view this thread, as many of the topics and opinions may be outdated.
 
styxer

May 22, 2005, 08:20 AM

hello all, I have the following situation: Class C inherits classes A and B. Say A has a function aFunc;


C ---> A
|
*----> B


I have an instance of C, say cObject, and somewhere in my application I call cObject->aFunc(). When inside this function of A, I'd like to try casting the this pointer to B, like B *bObject = dynamic_cast(this). Of course this cast always returns a NULL pointer. Can I get around this without changing the inheritance structure (having B inherit from C for example

 
styxer

May 22, 2005, 09:07 AM

Sorry, I got confused writing the text above. I correct, the case is actually the following:

GameObject---> LeafNode ------->GeneralNode
|
*------------> Renderable

I have an instance of GameObject, namely pObject for example, and am calling

pObject->traverse(),

where traverse is a function inside GeneralNode. I'd now like to cast to the indirect sibling Renderable inside my traverse function. Is this possible? GeneralNode certainly knows nothing about GameObject or LeafNode

 
Chris

May 22, 2005, 09:13 AM

How should it ? You must think of inheritance as a concept of child classes containing parent classes.

So GeneralNode contains a LeafNode which in turn contains a GameObject, but Renderable only contains a GameObject.

So you can cast Renderable only into a GameObject. Forcing a cast to a GeneralNode would crash when you access elements (data fields, virtual methods) of GeneralNode that are not also elements of GameObject.

I daresay your design is flawed here. Could you elaborate on the LeafNode and GeneralNode classes ? Why can't Renderable be a GeneralNode, e.g. are there Renderables that aren't Leaf/GeneralNodes ?
Why is GeneralNode a child of LeafNode, whereas I presume "General" is more general that "Leaf" ? Or is it odd naming only ?

 
styxer

May 22, 2005, 09:35 AM

Maybe my drawing is bad, the ">" is supposed to represent UML style inheritance.

LeafNode of course inherits from GeneralNode (as you say, it is "general"), and GameObject inherits from LeafNode, as well as from Renderable.

As the MSDN reference says on http://msdn.microsoft.com/library/default.asp?url=/library/en-us/vccelng/htm/express_72.asp, Figure 4.7 and the text below, it would be possible for me to cast from LeafNode to Renderable, but why not from one step deeper in my tree, i.e. from General Node to Renderable?

 
Chris

May 22, 2005, 09:40 AM

Ah, so I got it from the wrong side. I never liked UML ...

So GeneralNode is the root of the tree, and Renderable is another root, and both eventually join to form GameObject.

Then cross-casting is impossible for the same reason. LeafNode doesn't contain the definitions from Renderable, and vice versa. Same for GeneralNode. You can only cast when the cast destination is contained in the class originally used to create the instance to be casted.

BTW for me GeneralNode isn't "deeper" in the tree, it's the root. And GameObject is deepest. The deeper, the more inheritance levels took place. Is that different in english ?

The like you gave is broken.

 
styxer

May 22, 2005, 09:46 AM

I got it to work:

I had the GameObject "object" as a private member of some class X, but had it pushed on the stack, not initialized via "new". X being on the heap, I had "object" always in scope. I was working on it by reference. This way, the cast didn't work.

When allocating "object" dynamically, and working on it via the pointer, the cast works fine.

Nice to have it work now, but if anyone could explain to me why casts from heap and casts from stack give different results, I'd appreciate it.

 
styxer

May 22, 2005, 09:51 AM

thanks for the input Crhis, appreciate it very much

"Then cross-casting is impossible for the same reason. LeafNode doesn't contain the definitions from Renderable, and vice versa. Same for GeneralNode. You can only cast when the cast destination is contained in the class originally used to create the instance to be casted."

The class originally used to create the instance was actually GameObject, so when in my traversing function from GeneralNode (called on the gameobject though), I do have the definitions of LeafNode and Renderable. But as stated in the above post, I got it to work now.

The link seems broken because the "," at the end shouldn't be considered as part of the URL :)

 
Chris

May 22, 2005, 10:10 AM

If the instance was created from GameObject, all is fine indeed.
For such complicated situations I found this very convenient:

Have any root class publish a function like
virtual bool queryInterface ( InterfaceId _id, void ** _instance )

then you could define Ids for every class, and let the child classes override it and decide whether it wants to do the cast or not.

For example I had RenderTarget, from which WindowTarget and PBufferTarget derived. But the callee uses RenderTarget exclusively, and has no means to decide what kind of target it is.

Now RenderTarget declared queryInterface public abstract. Both target implementations overrode that declaration with their actual implementations, that denied casting a RenderTarget to a WindowTarget if it actually was created as a PBufferTarget, and vice versa.

It's overkill for such a simple situation, but pretty easy to extend.

The link seems broken because the "," at the end shouldn't be considered as part of the URL :)

Oh yeah, how dumb.

 
davepermen

May 22, 2005, 10:35 AM

link isn't broken. just take away the ',' at the end, wich got interpreted to be part of the link, but isn't..

http://msdn.microsoft.com/library/default.asp?url=/library/en-us/vccelng/htm/express_72.asp


that works

 
juhnu

May 22, 2005, 08:17 PM

dynamic_cast ?

 
Chris

May 23, 2005, 03:26 AM

Yeah, that let's the compiler do the appropriate checks. But it involves RTTI. That may or may not be appropriate for his situation.

 
This thread contains 11 messages.
 
 
Hosting by Solid Eight Studios, maker of PhotoTangler Collage Maker.