C ++: object type definition

I am curious what constructs or language functions available in both current C ++ and C ++ 11 can be used to infer an object type. Example:

class Base { }; class DerivA : public Base { }; class DerivB : public Base { }; void foo(Base* obj) { // Identify if `obj` is a `DerivA` or a `DerivB` } 

This is a simplification. It seems that instead of having a way to identify the type, the best solution is to overload the function for two derived types and eliminate the base class.

My real use case is where one class is not interested in the exact type of the object (i.e. just needs a Base implementation), and the other class needs to know exactly which Base implementation of the first class is used.

This happens in a component-based entity system. The base will be EntityState , and its derived types: StandingState , DeadState , etc. The Entity class is the one that needs only a generic EntityState , and the EntityRepresentation class must know exactly what state the subject must decide whether to draw a "standing" animation or a "dead" animation or something else.


Edit: Of course, if possible, I would like to implement the game in such a way that even the entity representation does not need to know the type of state of the object. If there is a way to do this, I would use it. :) I will consider the visitor template.

+4
source share
9 answers

You can use dynamic_cast for this:

 if(DerivA * derivA = dynamic_cast<DerivA*>(obj)){ // it is a DerivA } 
+6
source

Two ways:

If your classes are polymorphic, dynamic_cast

otherwise you can use typeid

Using typeid

 #include <typeinfo.h> typeid(YourClass).name() 

Using dynamic_cast

 DerivA& dynamic_cast<DerivA&> (object); DerivA* dynamic_cast<DerivA*> (object); 

there must be at least one virtual function in the Base class to make dynamic_cast work, or you will get compilation errors.

If you try to cast a pointer to a type that is not a type of the actual object, the result of the cast will be NULL. For a similar situation in case of links, the throw will throw a bad_cast exception.

+3
source

Take a look at the <typeinfo> standard library (for example, see here .)

+1
source

You can use dynamic_cast to identify the type of an object of a derived class. For example, when you do: DerivedA* p = dynamic_cast<Derived*>(pBase); if the condition p!=NULL satisfied, then its object is of type DerivedA .

+1
source

The problem described in the last paragraph can be resolved using the visitor template . Have you tried this? He can solve the problem without even knowing what type it works on.

+1
source

Contrary to most suggestions, I would not use RTTI directly (either type info or dynamic_cast). There are different things you can do:

  • add a function that provides the information needed for drawing
  • use dual send mechanism

The simplest solution is probably 1), just add a virtual method that tells you what state the object is in, and use it to determine how to animate the object. The problem with this approach is that it requires adding methods to the State classes for each of the things he needs: animation, sound, motion calculations ...

Using a double submit form, such as a visitor template, moves complexity from the state hierarchy to the visitors hierarchy, which must contain overloads for every other state (at all levels). The model in the application will be simpler, but using this model will become more cumbersome.

+1
source

Assuming your types have a virtual method in them, you can use C ++ real-time type identification (RTTI) with things like dynamic_cast and typeid

However, it is best to develop virtual methods to completely hide types. For instance:

 class EntityState { virtual void Draw( Entity entity ) = 0; } class DeadState : EntityState { virtual void Draw( Entity entity ) { //*** render the entity as dead } } class AliveState : EntityState { virtual void Draw( Entity entity ) { //*** render the entity as alive! } } class Entity { EntityState myEntityState; void Draw() { myEntityState.Draw( this ); } } 

Now your entities can be deleted either dead or alive without any if-then-else or switch code, which will need to be updated if you smoothly want to add new states to your entity.

0
source

Usually a better alternative than trying to query the type of an object would be to add a virtual function to the base class:

 class Base { public: virtual int Animation() const=0; }; class DerivA : public Base { public: int Animation() const { return 0; } }; class DerivB : public Base { public: int Animation() const { return 1; } }; 

And then you have all the different animations identified by this single integer, possibly having an unmodifiable array of animations:

 Animation anim1, anim2, anim3; Animation *array[5] = { &anim1, &anim2, &anim3 }; void foo(Base *b) { int animnum = b->Animation(); Animation *anim = array[animnum]; ... } 

This is at least one way to make it work correctly.

0
source

for inheritance, I would look at static_cast and dynamic_cast. You can use them to determine if an object is inherited from the class.

-1
source

All Articles