What you need first is a container able to hold your Enemy
instances or pointers to them. Most containers are templated classes, which have to be typed. One of them is the vector (a contiguous 'list'), which can be created in your case as
std::vector<Enemy>
: A 'list' holding your full objects
std::vector<Enemy*>
: A 'list' holding pointers to your objects
An example if you take references from your objects:
std::vector<Enemy*> enemies;
enemies.push_back(&object1);
enemies.push_back(&object2);
enemies.push_back(&object3);
If you are not familiar with pointers, you can look here, even though it may be a bit opaque at first!
Looping
A range for loop will let you iterate over your container pretty easily
for ( auto enemy : enemies ) {
enemy->doStuff();
}
The auto
will deduce the type from the container, and doStuff
will be executed sequentially for every enemy in your list. If your container contains instances instead of pointers *
, you will need to take a reference &
of the object instead, and use for ( auto& enemy : enemies )
. This will ensure your object is modified in place, and not copied, otherwise, your changes won't get reflected in the container.
Memory management
As mentioned in other answers, when you are ready to move to the next level, you can have a look at smart pointers. Because C++ code is unmanaged and has no out-of-the-box memory management, you are responsible for delete
ing any new
ed object. Smart pointers will help you more safely manage the lifespan of your data. Raw pointers (without any smart pointer to protect them) are considered bad practice in most situations nowadays.
However, your Enemy
instances are created on the stack, so they will get automatically destroyed at the end of their scope (function, {}
, ...). This also means that if you have any pointer *
or references to them that you use outside this scope, your object has been destroyed already, and you will encounter a memory exception or undefined behavior, i.e. Don't do that!