In my C++ project, I have an Engine
class and an Object
class.
My issue lies with how my instances of Object
are created. Currently this is done through the use of a CreateObject(parameters)
function in the Engine
class. This adds a new instance of Object
to an std::vector
of Object
instances.
I want to maintain this list of instances of Object
in my Engine
class, but without the need for the CreateObject(parameters)
function. My reason for this is so that I can create new classes that can inherit from Object
but still be added to this list. The reason for this list is so that (in Engine
) I can iterate through every Object
instance that has been created.
This would ultimately mean that I create my Object
instances with something like Object newObject = Object(parameters);
, but still have the Engine
class maintain a list of all Object
instances, without the need for Object
to reference the instance of Engine
or the list to add itself to this list (as in the instance of Object
should not know about the list it is in). Can this be done?
You can define a static collection data member in your Engine class, update it in your Object constructor and destructor:
class Engine
{
friend class Object;
...
public:
static std::set< Object* > m_instances;
};
class Object
{
public:
Object();
virtual ~Object();
...
};
You increment it in constructors, and decrement it in destructors.
Object::Object()
{
Engine::m_instances.insert(this);
}
Object::~Object()
{
Engine::m_instances.erase(this);
}
I think your factory pattern approach is the good way to achieve this. The engine manages all the instances of Objects internally.
But if you want to make external instances, managed by the engine too, you must have to access a instance of the engine; even if that instance is a global variable, even if the Engine class implements a singleton pattern.
The second best approach to do that (The first is what yoa are doint yet, the factory), I think is to implement a singleton in the Engine:
class Object
{
Object
{
Engine::instance().addObject( this ); //Note that engine stores pointers. STL containers cannot store references.
}
~Object
{
Engine::instance().releaseObject( this );
}
};
Use a static
vector<Object*> Objects
variable in Engine class and static public function
Push(Object* obj) { Objects.push_back(obj); }
to push Objects to the list. Then in constructor of your Object class you would call
Engine::Push(this)
Like many have mentioned, factory architecture is a nice and clean way to go, otherwise you are going to have to have a global instance, static members or a singleton. However, a static approach would be to
make Object
a friend
of class engine and make the members static:
class Engine{
friend class Object;
private:
static std::vector <Object*> objectList;
};
This will allow Object to access private members of Engine statically. Then in the constructor of Object, add it to the list like so:
Object::Object(int randomparam1, const char* randomparam2)
{
Engine::objectList.push_back(this);
}