c++ casting base class to derived class mess

15,281

Solution 1

If you store your objects in a std::vector<base> there is simply no way to go back to the derived class. This is because the derived part has been sliced of when storing it in an instance of base class (afterall your vector contains copies of your data, so it happily copies only the base part of your objectes), making the stored object a true instance of base class, instead of a derived class used as a base class.

If you want to store polymorphic objects in the vector make it a std::vector<base*> (or some kind of smartpointer to base, but not base itself) and use dynamic_cast<derived_3*> to cast it to the correct type (or static_cast, if its performance sensitive and you are confident enough that you are trying to cast to the correct type (in that case horrible things will happen if you are wrong, so beware)).

Solution 2

If you are using a vector of base then all your instances are base instances and not derived instances.

If you try to insert a derived instance, the object will be sliced. Inserting into a vector always involves a copy and the target type is determined by the type of the object that the vector holds. A vector cannot hold objects of different types.

Solution 3

Most of the time you shall not need to do this. A carefully designed class hierarchy can handle this by polymorphism (i.e. virtual functions).

If you really need to cast to the derived type, use dynamic_cast operator.

Share:
15,281

Related videos on Youtube

alan2here
Author by

alan2here

Updated on January 01, 2020

Comments

  • alan2here
    alan2here over 4 years

    If I were to create a base class called base and derived classes called derived_1, derived_2 etc... I use a collection of instances of the base class, then when I retrieved an element and tried to use it I would find that C++ thinks it's type is that of the base class, probably because I retrieved it from a std::vector of base. Which is a problem when I want to use features that only exist for the specific derived class who's type I knew this object was when I put it into the vector.

    So I cast the element into the type it is supposed to be and found this wouldn't work.

    (derived_3)obj_to_be_fixed;
    

    And remembered that it's a pointer thing. After some tweaking this now worked.

    *((derived_3*)&obj_to_be_fixed);
    

    Is this right or is there for example an abc_cast() function that does it with less mess?

    edit:

    I had to expand this into another question, the full solutions are shown there. stackoverflow.com ... why-the-polymorphic-types-error-and-cleanup-question

    • Matteo Italia
      Matteo Italia over 13 years
      Wait, is that a std::vector< base > or a std::vector< base * >? Because in the first case if you're storing objects of the derived class there's probably also some object slicing going on...
    • Matteo Italia
      Matteo Italia over 13 years
      Ouch. In general you shouldn't do that because, as already said, you will have object slicing (en.wikipedia.org/wiki/Object_slicing), which actually reduces all your objects to instances of the base class; if you want to store objects of various derived classes of the same class hierarchy you have to use a std::vector< base *>; this will keep the objects intact, although you'll still get them as pointers to the base class (see @Peon the Great's answer to see how to deal with them).
    • Oliver Charlesworth
      Oliver Charlesworth
      (derived_3&)obj_to_be_fixed may appear to work, but it hasn't!
  • Oliver Charlesworth
    Oliver Charlesworth over 13 years
    What you say is correct, but it doesn't address the most serious problem, i.e. the object slicing that's occurring.
  • Peon the Great
    Peon the Great over 13 years
    I do assume pointers are used in vector when I see this question. IMO throwing object instances into vector directly is a bad design. Standard library allocators guarantee only and were tested only with primitives and Standard library types. Anything other than those, pointers are better choices.
  • josesuero
    josesuero over 13 years
    Well, the point in the question is that pointers are not used in the vector. ;) and also whu? Standard library containers are designed to store values, not pointers. Often, storing pointers in a container is bad design.

Related