Sign in to follow this  
Peter Conn

Please an alternative for dynamic_cast/static_cast

Recommended Posts

Peter Conn    126
Hiya In my game I have an inventory (which at the moment is a vector of "Items") and I have made all the different types of items derived from that. Now I store my various items in that vector. Each item has a weight, name and description, other items have special variables (for example weapon has damage). How would I access a weapon's attack from the vector. Each item has an enum for its type aswell as a weight, name and description. At the moment I can only see dynamic/static_cast as an option for this, but I tried that and it said that my weapons attack was 150476 (ok, not that exactly but some random number) although I had set it to 5. [Edited by - Peter Conn on May 20, 2006 1:26:30 PM]

Share this post


Link to post
Share on other sites
Fruny    1658
Quote:
In my game I have an inventory (which at the moment is a vector of "Items") and I have made all the different types of items derived from that.


You cannot store objects of derived types into an array (or vector) of base types. Use an array (or vector) of pointers to base types instead.

Share this post


Link to post
Share on other sites
Peter Conn    126
But I thought that vectors used pointers anyway.
So would it be vector< *Item >.

And how would I get to the infomation?
Weapon *myWeapon = & Inventory[i]?

Share this post


Link to post
Share on other sites
nobodynews    3126
A vector copies the object given to it into some location in memory. Internally, it probably does use pointers in some form or another. And then when you reference the object like so data[i] it returns what is probabably a reference (I probably should know that by now).

To access the data, observe:

vector<SomeObject*> data;
SomeObject * pObject = new SomeObject;
data.push_back(pObject); / copies pObject, which contains the location of the SomeObject
pobject->action();
data[0]->action();
delete pObject;
data[0]->action(); // RUN TIME ERROR. You deleted the object, you can't access it!


EDIT: pointer after type

[Edited by - nobodynews on May 21, 2006 8:49:47 AM]

Share this post


Link to post
Share on other sites
Deyja    920
The * goes after the type. And vectors generally use a dynamically allocated c-style array.

Share this post


Link to post
Share on other sites
Guest Anonymous Poster   
Guest Anonymous Poster
You can use something like COM's IUnknown, or XPCOM's nsISupports.

dynamic_cast doesn't even work in some cases (mix gcc, linux, shared objects, and dlopen() and you'll know what I'm talking about.)

Share this post


Link to post
Share on other sites
Peter Conn    126
If I made the pointer in a function, then stored it in the vector (which is passed to the function by a reference) would there be any problems?
I think the pointer would get deleted, but not the allocated space that one of the vector pointers is pointing to.

Also, how would I access the variables that are only in Weapon then?

Weapon* myWeapon = Inventory[i];
myWeapon->_attack; ?

Share this post


Link to post
Share on other sites
jflanglois    1020
There wouldn't be any problem, really. You just need to be clear on who "owns" the object pointed to. Is it the container (std::vector in this case), or is it something else?

I recommend you look into boost::ptr_vector< Item > or std::vector< boost::shared_ptr< Item > > to avoid having to deal with lifetime of objects in the case that the container has ownership of the objects.

As for accessing weapons only, you would need to do a dynamic_cast, use home-made RTTI (barf), or rethink your design (what behavior does a weapon require in your design?).


jfl.

Share this post


Link to post
Share on other sites
Peter Conn    126
Thanks

I don't like the idea of rethinking my design, because otherwise my item class will have values for attack, defense and other things which would make it clumbersome.
What are the downsides of using dynamic_cast? I've heard its pure evil although I don't really know why.

Share this post


Link to post
Share on other sites
Sutekh    122
For a design rethink, what are you grabbing these values for? If you are just getting the item's values to generate a mouse-over popup of the stats and such, you could create a (pure) virtual function in the base class called "Description" which would let the derived class generate it's own info messages. This would also avoid having to use a RTTI and dynamic_cast type system.

On the other hand, if you are getting values from the item to perform some stat changes you could do a simple “ModifyStats” function in the base class that would pass stats into the item and then have the item alter the stats directly. Yet again avoiding any RTTI and dynamic casting

Share this post


Link to post
Share on other sites
joanusdmentia    1060
There's nothing wrong with dynamic_cast so long as it's used correctly, it's just that there's usually a better way. In this case, I think you'll be able to find a better way. I'd take the approach of allowing items to take on any property, for example:


class Item
{
public:

std::string& name();
std::string& description();

void addProperty(const std::string& name, int value=0);
bool removeProperty(const std::string& name);
int& property(const std::string& name);

private:

std::map<std::string, float> m_properties;
};



That would cover most properties an item would have, it would probably be acceptable to make the item's name and description separate from the properties (in fact, I'd consider them separate anyway). If you have the need for different types (ie. a string instead of a int) things will get a little more complicated, take a look at the boost::any library (and maybe the boost::property_map library as well).

Share this post


Link to post
Share on other sites
nobodynews    3126
Quote:
Original post by Deyja
The * goes after the type. And vectors generally use a dynamically allocated c-style array.


Thanks, I knew something felt wrong about that code. Like spelling 'conscious', I sometimes forget how it is supposed to be. Especially since I haven't actually done real coding in quite awhile.

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