-2

Is a lot of static casting a bad idea ? Is there a way to avoid static casting when using containers whose element type is a base class of some subclass hierarchy?

Example: The case of using

std::vector<GameObject> 

to store game objects. These objects are instances of classes Player, Enemy, Weapon and so on - which inherit from the GameObjectclass.

einpoklum
  • 118,144
  • 57
  • 340
  • 684
  • Pease make your question more specific. How much is "a lot"? Do you mean execution time spent casting, or instructions in your code? Can you give a code snippet which you feel has "a lot" of casting? – einpoklum Feb 02 '17 at 21:53
  • 4
    This simple would not work due to slicing. Read details here http://stackoverflow.com/questions/274626/what-is-object-slicing – Slava Feb 02 '17 at 21:56
  • Before using `std::vector`, you might want to check [What is object slicing?](http://stackoverflow.com/questions/274626/what-is-object-slicing) – Bo Persson Feb 02 '17 at 21:57

1 Answers1

2

Original answer

While your question is not very well defined, and it's not clear what you mean by "a lot" (instructions written in code, instructions invoked during a run, execution time actually spent casting), I'll give it a shot...

Yes, if you find yourself doing a lot of static casting there's likely a problem with your approach to the problem.

However, it seems that you're seeing "static casting" where there is none. Specifically, if you have a vector of (pointers to) GameObjects you don't need to cast from their actual type to GameObject - you're acting on them as GameObjects even though in fact they are something else, and that's perfectly fine (since they are GameObjects as well). Inserting Players or Weapons into your vector also doesn't involve any casting. If for some reason you're writing a lot of static_cast<GameObject&>(my_player) or similar statements - either that's unnecessary or you've sort of put yourself into some software design hole.

Answer after OP's edit

So, you have a std::vector<GameObject>s... well, like @Slava says, this won't work. Your static casts - that you probably use to insert things into your vector - are a bug - they 'slice' everything that's not part of GameObject as it's inserted.

What you might want to do instead is:

  • Use a std::vector<GameObject *> and act on your objects via pointers or references as I suggested above. This means that you allocate space for your GameObject somewhere at which you know what subclass it is, without slicing. You will have to take care of freeing that memory, though.
  • Use a or std::vector<std::unique_ptr<GameObject>>; again, you'll be accessing by a pointer - but it will be a "smart" one, which wraps a real pointer and takes care of deallocation. I suggested a std::unique_ptr above but there's also std::shared_ptr. This automation has costs, though, in the amount of space used during the game and the amount of time spent deallocating individual objects' memory.
  • Use an std::variant<Player, Enemy, Weapon>. That might be a bit clunky, but you'll have the storage for your GameObject within the vector, which is sometimes a plus. You'll access the relevant subclass instance with std::get<Player>(vector_of_objects[i]). See the description of std::variant for details.

Note these are not the only solutions, just a few alternatives based on your 20 characters of code...

Community
  • 1
  • 1
einpoklum
  • 118,144
  • 57
  • 340
  • 684
  • Would be worth mentioning the CRTP. – πάντα ῥεῖ Feb 02 '17 at 21:54
  • @πάνταῥεῖ: Perhaps you've made a better guess of what OP wants than I have. I mean, it could be that you're right, I'm just not seeing it. – einpoklum Feb 02 '17 at 21:58
  • @einpoklum if you have `std::vector` then you can only have GameObject objects and they cannot be instances of subclasses. – Slava Feb 02 '17 at 22:00
  • @Slava: I answered before OP edited his quesiton. I'll now change my answer... – einpoklum Feb 02 '17 at 22:00
  • @einpoklum Something like `std::vector>` seems to be an idiomatic solution. – πάντα ῥεῖ Feb 02 '17 at 22:01
  • @einpoklum if you have `std::vector` you cannot act on GameObjects via a refernce or a pointer. – Slava Feb 02 '17 at 22:03
  • @πάνταῥεῖ: Indeed, now that I saw OP's code. See my edit. – einpoklum Feb 02 '17 at 22:22
  • Ok I will try this another way. For example in ECS where you would have a base component and every component would inherit from the base. When your looping through all your entities and static casting the components to the right type of component. Hopefully this example is a bit better ? – user3220058 Feb 02 '17 at 22:59