Sorry your browser is not supported!

You are using an outdated browser that does not support modern web technologies, in order to use this site please update to a new browser.

Browsers supported include Chrome, FireFox, Safari, Opera, Internet Explorer 10+ or Microsoft Edge.

Dark GDK / Type Casting

Author
Message
Poof Master
14
Years of Service
User Offline
Joined: 14th Jan 2010
Location:
Posted: 25th May 2010 05:08
Can some one explain what is going on when I do a type cast like this:

MyClass *userdata = reinterpret_cast<MyClass *>(point->shape1->GetBody()->GetUserData());

I have tried to read the documentation and googled what a reinterpret cast is but I still don't know exactly whats going on.
JTK
14
Years of Service
User Offline
Joined: 10th Feb 2010
Location:
Posted: 25th May 2010 06:13
GetUserData() apparently returns a void*, I assume? reinterpret_cast will convert that void* into a MyClass* or; in other words:

MyClass *data = (MyClass*) GetUserData();

reinterpret_cast does not provide ANY type-safety checks at run-time. You should probably avoid its use (just a suggestion). If you know for a fact that GetUserData() will be returning a MyClass* then go for it... Otherwise, you're asking for trouble.

Now, for a more specific *description* - reinterpret_cast will allow you to reinterpret a value of one-type (say int) as another (say CMyClass*) - You are simply telling the compiler that you are aware that the two types are not the same, but giving it the ok to do whatever is necessary to try and treat them the same.

static_cast, like reinterpret_cast does not provide any run-time checks. With it too, you are telling the compiler that you are aware that they are not the same types, but fundamentally, they should be (int, float, short etc).

dynamic_cast, now this is nifty. With dynamic_cast, you are dealing with objects (as far as I've ever know) and you know that object1 is an object2 (or vice-versa) somewhere along the inheritance tree. dynamic_cast will try to verify the integrity of the source object (as the destination type) at conversion. If the cast fails, the result will be NULL... So, if:

CMyClass *data = dynamic_cast<CMyClass*>(Unrelated_Class);

fails, then (data == NULL) will be true...

Sometimes you can't avoid it, but if at all possible, try to avoid typecasting - it makes code easier to read, for one - not to mention the excess overhead you are adding for the conversion itself...

It does, however, have its uses - but use sparingly (just a suggestion)

I Hope this helps, and it may not be *correct* in the C++ standard sort of way, but this is how I understand these things to work. If anyone has anything to add (and/or clarify) - I would appreciate it myself...


JTK
Poof Master
14
Years of Service
User Offline
Joined: 14th Jan 2010
Location:
Posted: 26th May 2010 04:54
Hey JTK thanks for the explanation and with that I was able to get my code to work but I feel like it is very inefficient and I can't really think of a way to make it cleaner. Here is what I am doing:

I have a contact listener for my game and I am using box2d which they have a class that basically tells me when two of their physics objects collide. Here is the class:



"Add" gets called every time two shapes collide and I can get the specific user data from the two shapes with this:



Now that's why I was asking about the type casting because I wanted to type cast my GameObject class to that Userdata() so I could then call my functions from my game object class. Now I am doing this in order to run game logic. IE when my character gets hit or touches an enemy he takes damage.

So the basics of what I am doing kind of looks like this:

void ContactListener::Add(const b2ContactPoint *point)
{
GameObject* ObjectA = (GameObject*) point->shape1->GetBody()->GetUserData();
GameObject* ObjectB = (GameObject*) point->shape2->GetBody()->GetUserData();

}

Now here is where I think my code gets a little dirty. With this code I could essentially run functions from my game object class. Now lets say I want to run a function from my character class I would have to type cast it like this in order to do so.



Problem is I don't know if my character is going to be the object A or b. So my code is going to get a little out of hand with all the if checks that I am going to have to:





So do you have any suggestions on how to make this I guess more efficient.
JTK
14
Years of Service
User Offline
Joined: 10th Feb 2010
Location:
Posted: 26th May 2010 06:18 Edited at: 26th May 2010 06:21
I can't say for sure if it's more efficient, but I can try to explain things a little better for you... How's that?

First:

Quote: "Problem is I don't know if my character is going to be the object A or b. So my code is going to get a little out of hand with all the if checks that I am going to have to:
"


And that's where the dynamic_cast<> comes to play... Note: From my understanding of the subject - this is a perfect example of a "case-study" where dynamic_cast<> may solve the problem...

First off, for this particular "case-study" I am making the following assumptions (based upon your code and descriptions of the problem):

1) GameObject is a base class,
2) Character derives from GameObject, and;
3) Element also derives from GameObject.

That is:

class GameObject; // base class...
class Character : public GameObject; // Inherits from GameObject
class Element : public GameObject; // Also Inherits from GameObject

Now, with this, the dynamic_cast<> can be used to convert a pointer to a GameObject [which you're saying is returned from GetUserData()] into either:

a) Character, or;
b) Element...

Thus,




As far as my understanding goes, the above code should work (slightly modified for brevity); however, I personally would not use this approach. Given that my assumptions above are true (with regards to the inheritance structure above) - I (also assuming that GetUserData() is returning a GameObject*) would make the following design changes:

First, I would add an abstract method to class GameObject:



The HandleCollision() method would be a *required* addition to any inherited classes (ie: Character or Element) that would handle the collisions between itself and the collides_with GameObject...

This will allow the "short-and-sweet" form of:



In this approach, we *know* that GetUserData() - in this case - is *matter-of-factly* returning a pointer to a GameObject class; we just don't know if it's a Character or an Element.

Additionally, in either case, since it's a GameObject being returned (whether Character or Element), it knows how to handle its own collisions (as defined by the HandleCollision() method). And thus polymorphism kicks in...

I've probably confused you even more, but I hope not... I do hope this helps;

JTK
Poof Master
14
Years of Service
User Offline
Joined: 14th Jan 2010
Location:
Posted: 26th May 2010 06:57
Haha no this actually helped me a lot. I think making a function to run all my collision code would probably be the most efficient way of doing it. As for the function HandleCollision() I think one thing that I'm no to sure how to do is for instance when my character collides with an Element the collision code for hitting an element is going to be something like bGrabedElement = true but when my Character hits lets say a fire ball then it would run the TakeDamage() function. So how would I in my HandleCollision code know when the object that has been passed to it is a "Element" or "Fireball" rather than just a GameObject?

Thanks for the help thus far I really appreciate it.
JTK
14
Years of Service
User Offline
Joined: 10th Feb 2010
Location:
Posted: 26th May 2010 07:48
Well, if you know that all collisions will be between GameObjects, add a new membervar (ie: m_Type = FIREBALL, m_Type = PLAYER, m_Type = ASTEROID) that you can query at collision time via say:

if (objX->GetType() == FIREBALL) ... Of course, it's a new method added to the GameObject class that border on RTTI (Run-Time Type Information) but...

So, for this to work, you would need a class structure such as:

class GameObject;
class Enemy : public GameObject;
class Fireball : public Enemy;
class Asteroid : public Enemy;
class Player : public GameObject;
etc...

However, don't get carried away with the inheritance tree. It will slow you down (all of the indirect lookups / virtual function tables etc) if you get out of hand...

On the positive side though, that's what C++ does for you; allows you to break functionality down into types (Fireball, Player, Asteroid etc) even though they are basically the same (actions are different, but interface is the same)...

I once explained the difference between Inheritance and Polymorphism to my 10-year old nephew (years back). Back then, he was really into the "Mighty Morphing Power-Rangers".

Given that approach, inheritance goes as:



The beauty of this is that, whether Red, Green, Blue, Aqua etc, they all know how to Morph(), and they all have their own morphing-procedure that only *they* know how to do... We don't care *how* they do it, only that when we say to Morph() they know what we mean...

Each PowerRanger would perform a different action, but we can invoke that action via a common interface (a call to Morph())...

Sorry, a bit off topic here - rambling cause I'm tired I suppose... lol


JTK
Poof Master
14
Years of Service
User Offline
Joined: 14th Jan 2010
Location:
Posted: 26th May 2010 08:02
lol good reference to power rangers. Out of that whole post you reminded me that I created a function in my GameObject class called GetClass() and it returns a string so basically I will just say



Thanks for explaining this to me. Your awesome!
JTK
14
Years of Service
User Offline
Joined: 10th Feb 2010
Location:
Posted: 26th May 2010 12:31
This would work better...



JTK

Login to post a reply

Server time is: 2024-07-07 00:33:22
Your offset time is: 2024-07-07 00:33:22