Cast pointer from base type to child type

I am building a simple game project for my project. I have the following classes:

class Character { public: virtual void Display(); virtual void SetParameters( char* param, ... ); }; class NonPlayableCharacter : public Character { public: virtual void Display(); virtual void SetParameters( char* paaram, ... ); int GetNPCState(); } 

And then I have a bunch of classes that derive from either Character or NonPlayableCharacter. I define it like this:

 std::vector<Character*> _allChar; 

My problem is that at any given time I would like to perform some operation on one of the elements of the vector. Therefore, getting an element from a vector, I cannot directly call the GetNPCState() method, because the element in the vector is of type Character *. Thus:

 _allChar[0]->GetNPCState(); 

does not work. So I tried to do this with the famous dynamic_cast:

 NonPlayableCharacter* test = dynamic_cast<NonPlayableCharacter*>(_allChar[0]); test->GetNPCState(); 

The problem with this last attempt is that GetNPCState() fails because the object is null, and I know that the fact (via debugging) for _allChar [0] is not zero.

+6
source share
7 answers

There are several types of casts in C ++ (4), of which 2 are of interest:

  • static_cast assumes that you know what you are doing.
  • dynamic_cast checks at runtime that you β€œguessed” correctly.

Note: simplified, since dynamic_cast also allows broadcasts and broadcasts involving virtual databases.

There are 3 versions of dynamic_cast , indeed, depending on the nature of the target:

  • if the target is a link (i.e. dynamic_cast<T&>(u) ), then if the check fails dynamic_cast throws an exception std::bad_cast
  • if the target is a pointer (i.e. dynamic_cast<T*>(p) ), then if the tests fail, dynamic_cast returns a null pointer
  • finally, as a special case, if the target is void* , then dynamic_cast instead returns the address of the complete object

In this case, you can:

  • switch from dynamic_cast<NonPlayableCharacter*>(_allChar[0])->getNPCState() to dynamic_cast<NonPlayableCharacter&>(*_allChar[0]).getNPCState() , and the exception is thrown
  • check cast result ( NonPlayableCharacter* test here) for non-nullity
+6
source

After

 NonPlayableCharacter* test = dynamic_cast<NonPlayableCharacter*>(_allChar[0]); 

you should check if test NULL . Even if _allChar[0] not NULL, dynamic_cast can return NULL if the object it points to is not a NonPlayableCharacter .

So the correct version is:

 NonPlayableCharacter* test = dynamic_cast<NonPlayableCharacter*>(_allChar[0]); if (test) { test->GetNPCState(); } 
+5
source

dynamic_cast returns NULL if casting is not possible. Check what is inside _allChar[0] . You can make a function of type getType() where it returns an object of a predefined type identifier, and then use static_cast :

 if (_allChar[0]->getType() == TYPE_NO_PLAYER) { static_cast<NonPlayableCharacter*>(_allChar[0])->getNpcState(); } 
+3
source

You need to check dynamic_cast for success. It returns a null pointer on error:

 NonPlayableCharacter* test = dynamic_cast<NonPlayableCharacter*>(_allChar[0]); if (test) test->GetNCPState(); 

The problem may be that your first element does not point to a NonPlayableCharacter object.

+2
source

dynamic_cast returns NULL when its argument does not point to a NonPlayableCharacter (so the first element in the array probably points to some other subclass of Character ), so you need to check for NULL after the throw. However, using dynamic_cast may indicate a design problem. Perhaps you should instead have a virtual method on Character called for example. PerformMainActionInGameLoop() and is accordingly redefined in different subclasses?

+2
source

To get the child pointer from the base pointer, you need to use dynamic_cast . His behavior is as follows:

  • If the pointer points to Child* allocated using new Child , then dynamic_cast<Child*> returns Child*
  • If the pointer points to something else, then dynamic_cast returns NULL .

Your problem is that either you did not allocate with new , or your object is of a different type.

+2
source

It is probably best to use an OO solution to use dynamic_cast, but the whole point of using this actor is that it will return a NULL pointer if the failure fails.

So check for NULL before calling GetNPCState ();

 NonPlayableCharacter* test = dynamic_cast<NonPlayableCharacter*>(_allChar[0]); if( test != NULL ) { test->GetNPCState(); } 
+2
source

All Articles