Sign in to follow this  
deadstar

C++ How to tell if object is of a specific type

Recommended Posts

Hi all, I've been struggling with this, if only because I don't know the correct terminology. In my game I have a grapple gun which shoots rope and attaches itself to objects. Currently, it will attach to ANY object, but I'm trying to get it to only attach to objects which are derived from CGrappleObject. Here's an example:
class CGrapplePoint
{
   public:
      bool IsGrappled;
};

class CHealthPack : public CGeometry, CPickup, CGrapplePoint
{
   public:
      //Health pack related stuffs
};

Before shooting out a rope and attaching, I raycast ahead and see what to attach to. The raycast funstion returns a CGeometry* pointer, and I want to test to see if this object is also a CGrapplePoint object. I've tried the following:
if(dynamic_cast<CGrapplePoint*>(Raycastdata.Geometry)) ...
This always returns 0. And:
if(static_cast<CGrapplePoint*>(Raycastdata.Geometry)) ...
This gives me the compiler error:
error C2440: 'static_cast' : cannot convert from 'sym::CGeometry *' to 'CGrapplePoint *'
1>        Types pointed to are unrelated; conversion requires reinterpret_cast, C-style cast or function-style cast
Which is pretty obvious, because CGrapplePoint has no relation to CGeometry. What I DON'T want to do is have CGrapplePoint derive from CGeometry, which is probably what's making things complicated for me. I'm out of ideas for what to Google for. Any help appreciated.

Share this post


Link to post
Share on other sites
Searching for RTTI (run-time type information) should get you some details of how the dynamic_cast mechanism works. In this case your problem is probably that the base classes need to have a virtual function for dynamic_cast to function properly.

Share this post


Link to post
Share on other sites
Quote:
Original post by deadstar
I've been struggling with this, if only because I don't know the correct terminology.


What you're trying to do is a "cross cast" (search the page for "cross cast"), however I am unsure why it isn't working for you.

Are you sure the object you're returning is derived from both CGeometry and CGrapplePoint?

Share this post


Link to post
Share on other sites
Quote:
Original post by fpsgamer
Quote:
Original post by deadstar
I've been struggling with this, if only because I don't know the correct terminology.


What you're trying to do is a "cross cast" (search the page for "cross cast"), however I am unsure why it isn't working for you.

Are you sure the object you're returning is derived from both CGeometry and CGrapplePoint?


I think this is what I'm trying to do, yes.

In the above example, Raycastdata.Geometry is ALWAYS derived from CGeometry, and may sometimes derive also from CGrapplePoint too.

I'm testing with both kinds of expected objects, but the dynamic_cast always returns 0.

Does it matter that Raycastdata.Geometry will have been casted to CGeometry* beforehand? It's obtained using (CGeometry*)NewtonBodyGetUserData(Body) inside the Raycast function.

Share this post


Link to post
Share on other sites
CGrapplePoint has no virtual functions. As Nitrage suggests make sure your base classes have a virtual function in them so that the rtti mechanism (vtables) are activated to build the runtime type info that permits the cross casts. gcc is at least nice enough to give a compile-time error stating that the dynamic_cast is impossible without at least one virtual such as destructor.

#include <iostream>

struct A
{
// required for a->b cast
virtual void dummy() { } ;
};

struct B
{
// required for b->a cast
virtual void dummy() { } ;
};

struct D : public A, public B
{

};

int main()
{
A *p = new D;

// cross-cast a to b
B *b = dynamic_cast< B *>( p);
std::cout << "b is " << b << std::endl;

// cross-cast b back to a
A *a = dynamic_cast< A *>( b);
std::cout << "a is " << a << std::endl;
}

Share this post


Link to post
Share on other sites
try doing ,public CGrapplePoint or change the class to struct and see if it compiles.

Also, why are you inheriting? why not do


class CGrapplePoint
{
public:
bool IsGrappled;
};

class CHealthPack
{
public:
//Health pack related stuffs
CGeometry geometry;
CPickup pickup;
CGrapplePoint grapplePoint;
//i only made those public bc you made it public in your inheritance
//you also have the ability to do something like
operator CGrapplePoint& () { return grapplePoint; }
};


Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

Sign in to follow this