I still struggle to find areas where full-blown classical, class-based OOP is a good fit for the problem. Game development isn't such area.
Some claim (Like Gosling) that inheritance was never a major point of OOP and that it has been overused.
What do you mean by "tag" here. Is a "tag" implemented as a class in C++? Do you know of an example in real code that is open source, the the curious can study?
Google for "ECS", or "Entity-Component-System". It's a sorta-pattern for what I described. I say sorta, because everyone has a slightly different idea of how it's supposed to be implemented, but typically, entities are just dumb containers for (instances of) components, the components store data & type info, and systems mutate those components. So e.g. an asteroid in a game of Asteroids would consist of e.g. "kinematics" component, and "sprite" component, and a "collider" component. If you wanted that asteroid to drop a powerup on death, you'd add "drops powerup" component to it, possibly at runtime.
Components may or may not be implemented as classes, and the aggregation may or may not be direct. In small games where I used this (in Common Lisp), components were classes, and each entity object had a list of instances of those components. This was a naïve approach, but got the job done. A more performant implementation might look like this: each component is a struct, and gets a dedicated array of all instances; each entity only has a) tags of the types of components it consists of, and b) indexes into the "components" array. This optimizes for data locality, especially for more isolated systems. For instance, the physics system can now just loop over the array of "kinematics" components, and mutate their state, without knowing anything about actual game objects - and all the data necessary for updating physics for all game objects are close together in memory, reducing cache misses and allowing for other optimizations.
Note how this is a complete inversion of OOP - components are now storing just state, all behaviours get segregated into systems that operate on those components in batch mode, and entities exist only to tell you which instances of components together form a game object.
I don't have any reference C++ implementation handy to show, but if you read up on ECS, you're bound to find something.
Personally, at this point the way I write software is so far removed from this discussion that I just do what feels right and what people can generally agree on within my teams. Solve the problem, don't discuss code, discuss solving the actual problem.
Is a good post about how that can fail from the creators of starbound.
Relevant quote:
A new requirement comes in: I have an idea for a special kind of item that when the player holds it and its near a specific kind of enemy, it will glow. The enemies that trigger this should be scared of the item and back away, but have a special animation where they’re mesmerized by the glowing item. This should only work for players that have achieved some specific quest goal.
You throw up your hands in frustration [...]
"you can tell if someone started game development as a hobby because they ARE using an ECS."
Very interesting article here: https://www.gamedev.net/blogs/entry/2265481-oop-is-dead-long...
However, if you're designing an open-ended game engine for other people to develop in, then an ECS is a godsend, because you have no clue what they plan to make their game do.
I thought they actually just use structs and whatever data structure works.