• Advertisement
Sign in to follow this  

C++ instanceof?

This topic is 4648 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

A cookie for the first C++ programmer who knows what I'm talking about. N'eways, I'm trying to find out what type of derivative an object is. Like this: Base object; if(Base instanceof Derivative1) {do something;} if(Base instanceof Derivative2) {do something different;} I loved this feature in Java, but is there an easy way to do it in C++?

Share this post


Link to post
Share on other sites
Advertisement
Use dynamic_cast:

BaseClass * object = new DerivedA;

if ( dynamic_cast<DeviredA*>( object ) )
// do something

else if ( dynamic_cast<DeviredD*>( object ) )
// do something else
// ...



HTH,
Pat

Share this post


Link to post
Share on other sites
It should work, as long as you've enabled RTTI (some compilers by default disable RTTI since it costs a tiny bit of performance and is seldomly used).

Another option would be

template<typename CheckType, InstanceType>
bool isInstanceOf(InstanceType &Instance) {
return (dynamic_cast<CheckType *>(&Instance) != NULL);
}

if(isInstanceOf<Base>(pTheInstance))
cout << "mooh!" << endl;


but this requires RTTI as well. If I'm remembering right, Boost also provides a macro which can perform the check at compile time (of course, not including downcasts and ill-casted pointers ;))

-Markus-

Share this post


Link to post
Share on other sites
In C++ you can check the type runtime as follows:


// Suppose you have
class Car;
class Ferrari : public Car;
class BMW : public Car;

and then a function:

bool IsFerrari(Car *c)
{
// check if pointer of type Car can be converted to type Ferrari
Ferrari *f = (Ferrari *)c;
if (f != 0)
return true;
else
return false;
}

int main()
{
Car *f = new Ferrari;
Car *b = new BMW;

IsFerrari(f); // returns true
IsFerrari(b); // returns false

delete f;
delete b;
}


Share this post


Link to post
Share on other sites
The preferred way (even in Java) would be to provide the appropriate virtual member function in the Base class, overriding it in the Derived classes:


class Base
{
public:
virtual void DoStuff() = 0;
};

class Derived1 : public Base
{
public:
virtual void DoStuff()
{
// Do something
}
};

class Derived2 : public Base
{
public:
virtual void DoStuff()
{
// Do something else
}
};






Base* b = GetAnObject();
b->DoStuff();


Now, if in spite of this good advice, you really want to figure out whether you have a Derived1, Derived2 or even something derived from one of those classes, you may use, not typeid, which will only check for exact type matches, but dynamic_cast<Derived1>, which will check whether the object you have is really a Derived1 object - or an object derived from that class.

note: clb, your version doesn't work, a C-style cast "works" unconditionally, whether it is right or wrong.


Base* b = GetAnObject();
if( Derived1* d1 = dynamic_cast<Derived1*>(b))
{
// do something with d1
}
else if( Derived2* d2 = dynamic_cast<Derived2*>(b))
{
// do something with d2
}


Also note that you either need to have a virtual function in your Base class, or "enable RTTI" for dynamic_cast (and typeid, for that matter) to work properly.

Share this post


Link to post
Share on other sites
Right, I use virtual functions for doing things differently, I just wanted other objects to find out what kind of object it is. For example, if the player hits the "board vehicle" button, it would loop through the objects, checking if each one is close enough to get in. However, I want it to make sure each one is a "Vehicle" before I try to get in it. Before now, the player was "boarding" the gun he was holding!


Thanks for the help guys!

Share this post


Link to post
Share on other sites
Quote:
Original post by clb
In C++ you can check the type runtime as follows:

bool IsFerrari(Car *c)
{
// check if pointer of type Car can be converted to type Ferrari
Ferrari *f = (Ferrari *)c;
if (f != 0)
return true;
else
return false;
}



Are you sure that works?? IMHO C-style casts never fail (i.e. return null) unless the argument itself is null also. You'd have to use the dynamic_cast operator to achieve that functionality. Feel free to correct me if I'm wrong.

Share this post


Link to post
Share on other sites
Quote:
Original post by evanofsky
Right, I use virtual functions for doing things differently, I just wanted other objects to find out what kind of object it is. For example, if the player hits the "board vehicle" button, it would loop through the objects, checking if each one is close enough to get in. However, I want it to make sure each one is a "Vehicle" before I try to get in it. Before now, the player was "boarding" the gun he was holding!


Aha.

[google] "double dispatch".

Share this post


Link to post
Share on other sites
Quote:
Original post by clb
In C++ you can check the type runtime as follows:


// Suppose you have
class Car;
class Ferrari : public Car;
class BMW : public Car;

and then a function:

bool IsFerrari(Car *c)
{
// check if pointer of type Car can be converted to type Ferrari
Ferrari *f = (Ferrari *)c;
if (f != 0)
return true;
else
return false;
}

int main()
{
Car *f = new Ferrari;
Car *b = new BMW;

IsFerrari(f); // returns true
IsFerrari(b); // returns false

delete f;
delete b;
}



No, This code does not work as you think it does.

Both calls to IsFerrari return true, C style casts always succeed.

Share this post


Link to post
Share on other sites
You could do something like:


class Object
{
virtual char* Type() { return "Object"; }
};

class Item : public Object
{
virtual char* Type() { return "Item"; }
};


Thats just a suggestion, type comparison would take a string comparison and would be slow.

You could also do:


#define OBJECT 0

class Object
{
virtual int Type() { return OBJECT; }
};

#define ITEM 1

class Item : public Object
{
virtual int Type() { return ITEM; }
};


And with that you might try something like:


#define InstanceOf(x, y) ((x).Type() == (y))

Object *obj = new Item();
if(InstanceOf(*obj, ITEM))
cout<<"obj is an item."<<endl;


Just a suggestion.

Share this post


Link to post
Share on other sites
Or I suppose if you can spare an 32bit integer, I believe, for an enumeration or even an integer stating what the class is, might reduce the processing load, and only slightly increase memory usage.

Share this post


Link to post
Share on other sites
Quote:
Original post by evanofsky However, I want it to make sure each one is a "Vehicle" before I try to get in it. Before now, the player was "boarding" the gun he was holding!


Don't take this the wrong way, but this sounds like an inheritance-heirarchy problem :)

If you have control over the base code, or any of the heirarchies... I'd suggest re-writing the classes... and not putting objects like Guns and Vehicles on the same inheritance branch.

Not that this helps your immediate problem much

:D

Share this post


Link to post
Share on other sites
Quote:
Original post by ffx
if (typeid(object) == typeid(Derived1))
{
// do something
}


This is the answer, assuming you #include <typeinfo> first.

clb: C style casts are evil, and your broken code proves it.

Share this post


Link to post
Share on other sites
C-style casts perform reinterpret_cast<>, static_cast<>, and/or const_cast<> only.

Share this post


Link to post
Share on other sites
adding IsBoardable and Board functions to the base object is the WRONG way to guy, leading to infinite interface bloat as each new feature / type is supported.

The only correct way I know to do stuff like this is the way COM did it ...which is that each of your object's implements interfaces for each feature it supports, and also provides some mechanism for a client to test if an interface is supported (in a general way that isn't interface specific).

In COM this is QueryInterface

In pure C++ this is dynamic_cast<>

most people I see use dynamic_cast, are doing it for the wrong reasons ... to do stuff that IS supposed to be in a base interface, or virtual ... or otherwise tie clients and objects together inappropriatly. But when used this way, as a means ONLY of investigating for the implementation of published interface classes, then it works just like COM (almost) ... and is a great way to support extensible features in clients.

For the people who don't know why you'd use it ... his example is perfect ... say your "GetCurrentSubjectObject()" function returns a function pointer to whatever GameObject your character is acting upon ... but you don't know what that type will be exactly ... all the client knows is that it is trying to "Active" the object ... so it checks for dynamic_cast<IActvatableObject*>(subject) ... and if it finds can, it calls Activate ... otherwise it returns an ActionNotSupported result (and beeps the user) ...

Share this post


Link to post
Share on other sites
Quote:
Original post by Verg
If you have control over the base code, or any of the heirarchies... I'd suggest re-writing the classes... and not putting objects like Guns and Vehicles on the same inheritance branch.
:D


I disagree, as it's a very useful (not to mention common) approach for all objects in a game world to derive from a common base Entity/Actor/Pawn class. Many operations carried out on game objects are similar.

There's nothing wrong with comparing an object's type against another. Some people are quick to say that if you need to do so, your design is broken. Everything has it's place, though. Sometimes there are alternatives, but there is never a one-size-fits-all solution (as much as we would like for there to be). Perhaps type checking could be eliminated in this case by approaching the problem from a another angle.

For example, most (if not all) items in the game world (which should include vehicles) can likely be equipped, and conversely many game objects can equip other objects. By giving all equippable items functions to equip and drop other game objcts (and perhaps an onEquip function to be called on the object about to be equipped), you can then use context specific code to give the idea of 'equipping an item' a meaning appropriate to the item. In this case, equipping a vehicle could mean 'boarding' the vehicle. A gun could equip ammunition. Or you might want to use the term equip for something else, and call this 'attach' instead. Either way, it's a way of breaking several different actions down to one common method call. Of course, you still might need to do type checks to see if a particular object is equippable by another.

You might also use a message system, and each entity could process Game Messages such as GM_BOARD, GM_LOAD, GM_DRAW, and so on, ignoring the ones it isn't interested in. There's an example of such a system (in C) in Game Programming Gems 4 (based upon the Win32 message pump).

Anyway, there's more than one way to skin a cat. The best approach to take is the one that makes the most sense and doesn't hurt your performance too badly - and that can only be verified through profiling.

Share this post


Link to post
Share on other sites
I'll agree with you there is more than one way to attack the problem. Mine was merely another suggestion, based on the idea that the "everything isAn Object" isn't always very useful. OOP, of course, isn't always the best solution... and it's just my opinion that the one base class paradigm unnecessarily complicates OOP design. IMHOP an "Object" is too general an abstraction to be useful, but that's why there's a million of us programmers out there and not just two

;)

Share this post


Link to post
Share on other sites
Personally, I'm behind the dynamic_cast<>() idea.
Its used to great effect in the HL2 source, specifically with the vehicles to cast one generic vehical type to a more specific one to check its interface.
The HL2 vehicle heirarchy uses multiple inhertiance so it has to swap between interfaces alot, if it had tried to push them all into the public interface of the class you'd have interface_bloat++;

Share this post


Link to post
Share on other sites
Personally I'd go with the QueryInterface method already suggested. Seems a lot more elegant to me, although I'd probably be anally retentive, and use templates to get rid of the void** in QueryInterface.



class Jeep : public Entity, public IVehicle
{
//Implementations of IVehicle go here

bool QueryInterface ( UInt interfaceID, void** interfacePointer );

};


IVehicle* vehicle;

if ( entity->QueryInterface(VEHICLE, vehicle) )
{
vehicle->Board();
}

Share this post


Link to post
Share on other sites
how is that more elegant?


class Jeep : public Entity, public IVehicle
{
//Implementations of Jeep go here

};

if ( IVehicle *entity = dynamic_cast<IVehicle*>(someentity))
{
vehicle->Board();
}


simple, compact, doesnt rely on you maintaining your code thus less potential mistakes and uses the language constructs... doesnt come much more elegant than that.

Share this post


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

  • Advertisement