I use composition a lot too and most of my classes are made up of a few interfaces.
Lets look at it this way, consider this: you have many objects that need to be drawn to the screen via a 'draw()' method. You also want to update them every frame to compute their collisions, etc.
We will call the classes Car, Boat, Plane, Man, Box.
Now, without composition or inheritance you would need to have the following arrays:
std::set<Car*> mCars;
std::set<Boat*> mBoats;
std::set<Plane*> mPlanes;
std::set<Man*> mMen;
std::set<Box*> mBoxes;
// Then to update and draw...
for (auto c : mCars)
{
c->update();
c->draw();
}
for (auto c : mBoats)
{
c->update();
c->draw();
}
// Etc.. etc...
This is really messy and breaks the DRY principle of 'Don't Repeat Yourself'.
Lets look at this problem another way.
Although cars and boats and men etc. may have different members and different methods, they all share two common methods, draw() and update(). Each class will implement draw and update differently - for example the car might calculate it's fuel remaining in update() and draw a picture of a car on screen in draw(). Whereas a person might calculate their age in update() and draw a picture of a person in draw();
Because all the classes share these same methods, we can implement an interface that declares these methods, but allows each class to implement it differently.
consider this code (I'll just use Car and Man to save space):
class iGameEntity
{
virtual void draw() = 0;
virtual void update() = 0;
};
class Car : public iGameEntity
{
virtual void draw() override { mRenderWindowPtr->draw("PictureOfCar.png"); }
virtual void update() override { mFuelRemaining -= 1; }
};
class Man : public iGameEntity
{
virtual void draw() override { mRenderWindowPtr->draw("PictureOfMan.png"); }
virtual void update() override { mAge += 1; }
};
// Then we can store all our entities like this
std::set<iGameEntity*> mAllEntities;
// Add some cars and men
mAllEntities.insert(new Car());
mAllEntities.insert(new Car());
mAllEntities.insert(new Man());
mAllEntities.insert(new Man());
mAllEntities.insert(new Man());
// Then to call the methods we simply do this
for (auto e : mAllEntities)
{
e->update();
e->draw();
}
Now, we only need one container, and we only need to loop over it once to call the draw() and update() methods of every game object.
But the real beauty is that every subClass of iGameEntity does something different when draw() or update() is called.
Hope this helps get your head around OO coding.