C++ copy constructor with subclasses

Member
Posts: 156
Joined: 2002.10
Post: #1
Quick C++ question!

I have a class hierarchy as follows:

superclass:
Weapon - pure virtual class

subclasses:
MachineGun
RocketLauncher
etc. etc.

At game startup I load a bunch of weapon data from an XML file, and keep them in a std::map<int, Weapon*> so I can then get an instance of a weapon looking them up by ID. Note that depending on the data in the file, different subclasses of Weapon will be constructed and stored in the map.

The trouble is, I obviously don't want to have every player in the game using the same instance of a weapon, so I want to use a copy constructor to copy the objects out of the map for use in game e.g.

player1.AddWeapon(new Weapon(*(weaponmap[0])));
player2.AddWeapon(new Weapon(*(weaponmap[0])));

The idea being that the two player objects should now have identical, but distinct weapons, each initialised from the object in the map. Trouble is, using a copy constructor on Weapon doesn't work as it's an abstract class (contains pure virtual functions).

The obvious solution to this is to load a new object from the XML file each time, and construct the correct subclass, but it would be nice to be able to load from file only once, and then copy the created object.

Anyone got any thoughs? How do I create a copy of a derived class object when I only have access to the base class pointer?

Cheers

- Iain
Quote this message in a reply
Sage
Posts: 1,199
Joined: 2004.10
Post: #2
Probably you should have your map store something like a "WeaponInfo" class, which has all the parsed data from XML.

Then, you'd have a constructor for your weapons which takes a WeaponInfo for initialization.

Code:
WeaponInfo info = weaponmap[ ... ];
player1.AddWeapon( new Weapon( info ));
player2.AddWeapon( new Weapon( info ));

Either that, or implement something like a clone() method for your weapons.

Code:
class Weapon {
...
virtual Weapon * clone( void ) const = 0;
...
}

Each weapon class would implement clone. And then you'd have the following:

Code:
player1.AddWeapon( weaponmap[...]->clone() );
player2.AddWeapon( weaponmap[...]->clone() );
Quote this message in a reply
Moderator
Posts: 592
Joined: 2002.12
Post: #3
You could add a member function to the Weapon class that returns its type.

Then when you come to the copying you can cast the pointer to the relevant subclass of Weapon and then do the copying.
Quote this message in a reply
Member
Posts: 156
Joined: 2002.10
Post: #4
I like the clone idea, will give that a go...

Thanks.
Quote this message in a reply
Moderator
Posts: 1,140
Joined: 2005.07
Post: #5
If you're doing this by ID, and all the types are only brought in at load time, then why not just put them in an array or vector? I think constant access time would be much preferable to lg(n) with map. Rasp
Quote this message in a reply
Member
Posts: 156
Joined: 2002.10
Post: #6
It's part of a plugin architecture, and so I don't necessarily know what IDs there will be, or that they would even be a continuous range...

Anyway, all is working now with a Clone() function.

Thanks.
Quote this message in a reply
Moderator
Posts: 1,140
Joined: 2005.07
Post: #7
If that's the case, then I recommend hash_map instead of map, since it will be almost constant time without any requirements in terms of number or continuity. (since the size will be relatively constant, since it should be created at load time, so you won't have to take the hit of re-hashing)
Quote this message in a reply
Post Reply 

Possibly Related Threads...
Thread: Author Replies: Views: Last Post
  Copy Protection Barclay 2 2,417 Apr 20, 2006 02:37 PM
Last Post: KittyMac
  c++ constructor question Najdorf 7 3,094 Nov 28, 2005 04:45 PM
Last Post: Hog
  is the copy method broken in Tiger? Andrew 7 3,610 May 30, 2005 04:52 AM
Last Post: OneSadCookie