I'm developing a game for a course at my school. One of the assignments is to enable saving the game to a file and later load the game from the same file.
The problem I'm having are pointers. I'm not allocating anything on the stack (due to ownership of an item for example) so all the classes have pointers to whatever they want a reference to.
While this is quite easy to solve (assign an ID to each object and store that id instead of the pointer) the real problem comes with multiple inheritance.
Let's take the class Actor for example. It looks like this: class Actor : public Object, public ItemOwner where Object is a Obj-C-style base class which has a retain count and release, retain and autorelease methods. ItemOwner is simply an Interface which has some methods such as virtual bool add(Item *item) = 0;, virtual void remove(Item *item) = 0; and virtual bool transfer_ownership(Item *item, ItemOwner *new_owner) = 0;
Now the real question comes, which class(es?) should have ID's. And Item has a pointer to an ItemOwner while a Room has a pointer to an Actor.
The actor should only be saved once.
I've thought about assigning ID's to each superclass (Object, ItemOwner, etc) but if I have a pointer to an Actor will that actor always have the same adress as the Object it contains (Actor *foo = new Actor(); foo == (Object *)foo)? If not every single class in the game will need to have an ID.
Any thoughts or suggestions would be greatly appreciated.
By using UIDs, you create a mapping:
serialized_object -> UID -> deserialized_object.
Why bothering? You already have UIDs, and these are pointers to objects. By using this mapping:
&serialized_object -> &deserialized_object
you drop a level of indirection, UIDs as created automatically, and all you have to do is to deduce this mapping in deserealization process.
The simpliest way is to serialize the objects with all the pointers as is, and to store together with each object its address. This will also help you check if an object was serialized alraedy.
While serialization would be simple, deserialization will have its tricks. You'll have to be carefull to update each old pointer (remember? they contained adresses that are no more valid) with the correct object address.
One option is to define a class who's purpose in life is to hold an ID, and make it a virtual base class of every class you intend to save to disk.
I would put a single per object instance, for the actor, its ID should be the same for the Object and ItemOwner, because they are all the same instance.
Also, instead of using pointers you can think about using handlers, like described here: http://gamesfromwithin.com/managing-data-relationships
Related
Recently, I decided that it was time that I should dig into smart pointers. I read about the different kinds (unique, shared, weak), but I'm not sure about one thing.
Let say that I have a class Player and a GameMap class. The content of those classes are irrelevant for the next part. I also have an Engine class, that represents the object that will hold the main components of my game, like this:
class Engine {
public:
Engine();
~Engine();
private:
std::unique_ptr<Player> m_player;
std::unique_ptr>GameMap> m_gamemap;
};
These are the only instances of the player and game map that will be created, and the Engine owns them, and should be responsible for their allocation and deletion. So, a unique_ptr seems to be the good choice here.
Now, I would like to keep a simple reference to m_player in my GameMap class, since it would be easier for me than passing the m_player to each function that need it.
My question is: is using a raw pointer (obtained through the get() method) in the GameMap class the best way to keep a reference to the original unique_ptr located in the Engine class? I think that I can't use another unique_ptr pointing to the original one, since it would not be logical regarding to the use case of unique_ptr.
I think that using of raw pointer isn't the best way. For example, better way is use shared_ptr for player and gamemap. And adds weak_ptr of player into gamemap.
I have a quick question.
I started learning C++ a while ago and have always used vectors with shared pointers of objects in them. Or at least smart pointers.
I'm currently programming a game and I was thinking about why I would use smart pointers.
Assume I have a Game class and it has a vector of players.
When would I want to choose for
vector<Player> players and when would i want to choose for vector<shared_ptr<Player>>?
Use shared_ptrs if the state of the entities is accessed other than in the vector. Also if you make an event-loop, with events like "player collided with other entity". You need to copy a pointer/reference, else you cannot change the state of the entities.
Another important thing is when the entity dies but an event with the entity is not handled, so the entity is deleted from the vector. When you use shared_ptr, the entity lives further, until the event in the eventqueue is deleted. When you store the whole player in the vector, the pointer stored in the event-object is not pointing to the correct entity anymore, if the vector changes its size. When you use a shared_ptr, the entity can be used normally, even if it is not existing in the vector anymore. But it is better to use std::weak_ptr in the event, that the entity is deleted, when it is dead, weak_ptr can check if the pointer is a dangling pointer which means the entity is dead and no event needs to be handled.
Using levels/dimensions, in which the vector of entities lives: When some entity goes to another level, the entity needs to be moved to that level, copying the whole struct is not the best idea. So the best idea is to use some pointer type like shared_ptr, but I recommend to std::move the shared_ptr to reduce reference counting overhead. With std::move the shared_ptr is as fast as a raw ptr.
Virtual classes of entities: When you are writing a game in a 2D or 3D world, you want to store many entities of different kind in the vector, you must use some pointertype to refer to the object, because the entities may have different size.
Fixed player count: If you are programming a game with fixed count of players like a card-game, you do not move the players nor you delete one (however you can just set a flag to indicate that the player is dead and you do not need to erase the entity from the vector), the best way is to use std::vector<Player>.
I think, using shared_ptr living in the vector and with weak_ptrs referencing in events is the best way to manage entities. While weak_ptr(the faster way) does not keep the memory of the Entity alive, the pointer needs to be checked every time.
Some pseudo code
if(fixed count of players
&& there are no other entities
&& there are no virtual subclasses of Player) {
class Player { ... };
using player_collection = std::vector<Player>;
using reference_to_player = Player*;
} else {
class Entity { public: ... virtual ~Entity(); };
class Player: public Entity { ... };
using entity_collection = std::vector<std::shared_ptr<Entity>>;
using reference_to_entity = std::weak_ptr<Entity>;
};
I have the following classes:
class ActivityItem : public QGraphicsItem;
class DeadTimeItem : public QGraphicsItem;
I am at a point where I need to store both objects of type ActivityItem and DeadTimeItem in the same container so I can work with them together.
What have I tried?
I tried creating a QVector that stores QGraphicsItem type, but I got the result that it cannot store abstract class types. What should I do?
My plan
My plan is to store these elements into QVector<T> member of a class timeline, because they will create a timeline. For example:
class timeline : public QGraphicsScene // is this a good idea? to inherit QGraphicsScene?
{
private:
QVector<QGraphicsItem*> items;
int left_offset; // this is for putting the items next to each other
public:
timeline();
void add_item( QGraphicsItem *item );
~timeline();
}
My timeline should look like the sketch below:
So, when the user calls add_item() method,
Timeline *timeline;
timeline->add_item( new ActivityItem( /* parameters */ ) ); // timeline->left_offset += 150;
timeline->add_item( new DeadTimeItem( /* parameters */ ) ); // timeline->left_offset += 100;
the left_offset increases depending on the type of the inserted item.
I know my post is quite long, but please read it completely, because I really need your help! Thank you!
As you've already guessed, I am using Qt. I can also use boost if it is really necessary.
Assuming
QGraphicsItem objects are part of the same scene and have a parent
The list is tightly tied to the scene (member variable of the same class which owns the scene, or member variable of a scene subclass).
Then you should use this:
QList<QGraphicsItem*> items; // or QVector or std::list, nearly same
These are raw pointers, they will not automatically delete the object when removed from list, nor will they get notified when item is deleted. Still, I don't know of a smart pointer type, which would work with QGraphicsItem, so raw pointers are what you must use. So if you need to also remove items dynamically, read on:
First of all, when you delete item, you need to also remove the pointer from this list, to avoid having dangling pointer. As an example, you may want to use something like QList::indexOf() and QList::removeAt() methods for this (also, if removal is very common and there are many items in the list, you may need to rethink the approach, as removing from an big array is slow). You need to be careful that item doesn't get deleted by some Qt code without you having a chance to remove it from the list.
Things get more complicated, if you may have items in the list, which also have their children in the list. If you just delete an item, it will delete it's children, so if your list has pointers to these and your list will end up with dangling pointers to those children. So, you need to do deletion very carefully. There are at least 3 different ways to go about this I can think of (recursive deletion in your own code, removing from list in item destructors, using event filter to catch item removals), so I can expand the answer, if this situation can happen in your code.
Final note: when the entire scene is deleted, it will delete all its children. Only thing you need to do here is make sure the pointers to deleted items in the list don't ever get used, for example simply by clearing the list.
You cannot create an instance of an abstract class, which is fortunate, because trying to assign a derived class to a base class provokes slicing or misbehaves in other interesting ways.
Due to the above restriction, no standard container for base can store a derived. You can circumvent this limitation by using pointers to base, either raw (non-owning) pointers or some smart-pointer type.
The answer using the standard library would be something like:
std::vector<std::shared_pointer<QGraphicsItem>> v;
Using QT classes:
QVector<QSharedPointer<QGraphicsItem>> qv;
I'd like to have some help on an issue I face.
I'm using serialization (TinyXml to be precise) to save objects in a file and I have a problem on deserialization.
My objects contain pointers, which are not saved directly but instead the ID of the object pointed to is saved.
Every object I save derivate ASerializable, directly or not.
Here is my hierarchy :
//Holds pure virtual method: TiXmlElement * ToXml() = 0;
class ISerializable;
// Basic implementation of ISerializable, this class has a unique ID.
class ASerializable : public ISerializable;
// For security sake, this class is not real, just a demonstration of my problem.
// Overrides TiXmlElement * ToXml()
class Base : public ASerializable;
// Overrides TiXmlElement * ToXml()
class Derived : public Base;
Upon deserialization, I add each object I create into a static map(ID, ASerializable*), which holds the data until dereference.
How I dereference objects
I use a template class which holds a T**, which is the pointer to dereference once all the deserialization is done.
template<typename T>
class Reference<T> {
T** ref_ptr;
int id; // This is the ID of the referenced object
void Dereference();
}
Basically, Reference<T>::Dereference() gets the object in the map, then cast it to the good type (which is T*) and change the value of *ref_ptr to the cast object.
I'm using dynamic_cast<T*>( objects_map[id] ) to cast my object and for some reason, it fails everytime.
I can't cast from a ASerialisable* to a Derived* without losing the data of Derived.
Here is the pattern I want to achieve :
On deserialized, the item add itself to the objects map;
If the object is a reference, add a Reference (with the good type, I know it) to a Stack
Once all deserialization is done, unstack all references and calls Dereference()
Be really happy.
Thank you soooo dor your time and precious help, really appreciated.
{enjoy}
EDIT :
Okay, I'll try to be clearer, but it is a bit complex.
When I parse my XML file back, there are sometimes element called <reference id="X"> : those are reference to another instance (ASerializable);
When I encounter a <reference> object, I add it to a stack, to be dereferenced later.
When I encounter a specific object, like a <Base id="X" ... data ... /> I build it, then I add it to a object map, as an ASerializable*;
Once I finished building all my objects, I unstack each of the reference and call Dereference(), that SHOULD go get the REAL INSTANCE of the object, cast it to the good type using dynamic_cast then change the value of his ref_ptr to point that object.
Don't hesitate to ask for other questions if needed.
Does your base class have at least one virtual method? If it has none, make the destructor virtual.
You might want to look into using Boost.Serialization, it handles serializing to and from XML files nicely.
Alright, thank you all for your time. I found the problem.
Everything was fine in my hierarchy, the problem was a vector that was being copied. The pointers it contained were then changing so my the ref_ptr of Reference was corrupted.
{enjoy}
I'm kind of new to C++ development in linux and I'm trying to make a multiplayer game. I know that it is a bit of complex program to start but I have some background on this type of program from other languages so I guess the most difficult part is taming the language.
Although I'm programming a multiplayer game, my doubts are about the best way to handle the memory and avoid leaks in C++.
My doubts are about allocating memory for the client objects and for the game tables. For the client objects I've read that the std containers handle the memory allocation for me. I don't know if this memory is allocated on heap so I've decided to use a map of pointers (with the socket fd as key) to client object. This way, I have something like this when a client connect and disconnect:
Daemon.cpp
map<int,Client*> clientList;
//Do server stuff
//Add connected client to list
void onConnect(int socketFd) {
clientList[socketFd] = new Client();
}
//remove connected client from list
void onDisconnect(int socketFd) {
delete clientList[socketFd];
clientList.erase(socketFd);
}
The Client class is a simple class that has a virtual destructor, some client parameters (like IP, connected time, etc) and some methods (like send, etc). Is this the best way to keep track of clients without memory problems? I guess I still have to add exceptions handling on new Client() allocations...
The second part, and I guess the most difficult for me, is about the game tables. Clients can enter and leave tables of games. I have a table class with a lot of parameters, constants and methods. I'm creating all the game tables on start up on the same Daemon.cpp described above:
Daemon.cpp
GameTable *tables;
int main() {
tables = new Chess[MAX_NUMBER_OF_TABLES];
}
Some explanations: GameTable is the base class for all games. It is an interface with base parameters and virtual game functions (like doCommand, addClient, removeClient, etc). Chess class is the implementation of the chess game, it inheritance (sorry bad english) from GameTable. Questions:
1) Is this the best way (memory) to handle it?
2) Chess class has a lot of parameters, when I allocate the table list of Chess objects do the memory for all objects already allocated or I have to allocate and dealocate inside Chess class (with constructors and destructors)?
My third question is how to add and remove clients to/from tables. First I thought in creating a simple vector with clients like:
GameTable.h
vector <Client> clientInTable;
Chess.cpp
//Add client to table
void addClient(Client &client) {
clientInList.push_back(client);
}
//remove client from table
void removeClient(Client &client) {
//search client on list, when found get position pos
clientList.erase(pos);
}
Soon I've noticed that when I remove the client its destructor was called. It must not happen! Than I thought in use a vector of pointers like:
GameTable.h
vector <Client*> clientInTable;
Chess.cpp
//Add client to table
void addClient(Client *client) {
clientInList.push_back(client);
}
//remove client from table
void removeClient(Client *client) {
//search client on list, when found get position pos
clientList[pos] = NULL;
}
Is this the best way to handle it? Thanks everybody for the help.
Everything that is dynamically allocated should have something that 'owns' the responsibility for deleting it - typically this should be an auto allocated struct/classs that uses RAII.
Use smart pointers such as std::auto_ptr and std::tr1::shared_ptr to store dynamically allocated objects, and use memory managing containers such as boost::ptr_vector and boost::ptr_map for storing multiple dynamically allocated objects in a single container.
Doing this kind of thing manually is error prone, difficult and, seeing as good solutions already exist, pointless.
This:
GameTable *tables;
int main() {
tables = new Chess[MAX_NUMBER_OF_TABLES];
}
Is extremely dangerous. An array of Chess cannot be used interchangeably with an array of GameTable. The compiler lets it pass because a pointer to Chess can be used as a pointer to a GameTable.
Arrays are contiguously packed - if size_of(Chess) is different to size_of(GameTable), indexing into the array will result in indexing into the middle of an object possibly followed by an access violation (that's the most likely scenario, you're actually invoking undefined behaviour).
Using smart pointers is a good way to avoid memory leaks
Consider boost ones:
http://www.boost.org/doc/libs/1_42_0/libs/smart_ptr/smart_ptr.htm
A good strategy would be to set statically the maximum number of clients that can be managed by your server.
Then you build all Client objects required to manage all the clients from start (in an array or vector).
You will then re-use Client objects when there is a new connection, end using one when the client disconnects.
That require that your Client object is made in a way that allow reuse : the initialization and "termination" of it's use have to be explicit functions (init() and end() for example, something similar).
When you can, allow from start all resources you will ever need and reuse the objects. That way you limit memory fragmentation and get faster to the "worst case".
Inside onDisconnect, I would recommend calling clientList[socketFd] = NULL; after the connection is destroyed. This would make sure you aren't keeping an already-freed pointer around which can open up the door for problems later. This may already be handled by your clientList.erase method, but I thought I'd mention it just in case.
There might be a problem with the way you declared your Chess array. The pointer tables is defined as a pointer-to-GameTable, but it is pointing to an array of Chess objects. If a Chess object is nothing more than a GameTable object with a different name, then this code should work. However, if the definition of Chess adds anything to itself after it inherits from GameTable then you will change the size of the object and you will not be able to iterate through the array with that pointer. For example, if sizeof(GameTable) is 16 bytes and sizeof(Chess) is 24 bytes (perhaps due to some added member data), then tables[1] will refer to a memory location in the middle of the first Chess object in the array, not the beginning of the second item in the array as intended. Polymorphism lets you treat a derived class as if it were an object of its parent's class for the sake of using inherited members, but it's not safe to cast a pointer to a derived type into a pointer to the parent type for the sake of accessing an array.
Regarding adding clients to tables, can a client be associated with more than one table at a time? If not, give each table a unique ID of some sort and give each client a field called (for instance) current_table. When the client joins a table, store that table's ID in the field. When the client leaves the table, zero out the value. If a client can join multiple tables, this field can be turned into an array (current_tables[MAX_TABLES_PER_CLIENT]) and treated similarly.
Alternatively, you can create something like:
struct mapping {
clientId_t client_id;
tableId_t table_id;
};
struct mapping client_table_map[MAX_NUM_CLIENT_TABLE_MAPS] = {0};
When a client joins a table, create a new mapping structure containing the unique IDs of the client and table and add it to the list. Delete the entry when the client disconnects from the table. Now, you will have a table of all current connections that you can cross-reference in either direction (find all clients using a table or find all tables in use by a client).