Here's how I did mine. I have a global gTextureManager class which returns handles to textures, you get the handle by the filename and when you don't need the texture anymore you tell that to the manager and it decreases the usage counter for that texture.

When the texture's usage counter is 0 it means that this texture can be replaced by another. Textures used for the same purpose usually are the same size and glTexSubImage is used to replace the data in the graphics card's memory.

Another way to do it would be to use massive texture sizes, ie. allocate as big texture as possible and then start fitting the actual textures in that, a sort of texture atlas. This would reduce the number of state changes when binding textures. But you'd probably need several textures and handling all the reallocation can be tricky and the texture classes should handle all bindings themselves, no more calling glBindTexture directly with a handle and setting the texture coordinates would be tricky too (would have to alter the texture matrix). I might try something like this next.