Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Casting pointer from base type to child type

I'm building a simple game design for a project of mine. 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 either from Character or NonPlayableCharacter. I define it like so:

std::vector<Character*> _allChar;

My problem is that at any given time I would want to perform some operation on one of the element of the vector. So getting an element out of the vector I can't directly call the method GetNPCState() because the element in the vector are of Character* type. So doing this:

_allChar[0]->GetNPCState();

doesn't work. So I tried doing it with the famous dynamic_cast:

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

The problem with this last attempt is that GetNPCState() crashes because the object is null, and I know for a fact (via debugging) that _allChar[0] isn't null.

like image 240
TurnsCoffeeIntoScripts Avatar asked Oct 22 '12 14:10

TurnsCoffeeIntoScripts


People also ask

How a base class pointer can be converted to derived class member?

Explanation: A base class pointer can point to a derived class object, but we can only access base class member or virtual functions using the base class pointer because object slicing happens when a derived class object is assigned to a base class object.

Can you cast a pointer?

You can cast a pointer to another pointer of the same IBM® i pointer type. Note: If the ILE C compiler detects a type mismatch in an expression, a compile time error occurs. An open (void) pointer can hold a pointer of any type.

Why downcasting is not safe in C++?

Downcasting is not allowed without an explicit type cast. The reason for this restriction is that the is-a relationship is not, in most of the cases, symmetric. A derived class could add new data members, and the class member functions that used these data members wouldn't apply to the base class.

What is the use of Upcasting and downcasting in C++?

The Downcasting is an opposite process to the upcasting, which converts the base class's pointer or reference to the derived class's pointer or reference. It manually cast the base class's object to the derived class's object, so we must specify the explicit typecast.


1 Answers

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

  • static_cast assumes that you know what you are doing
  • dynamic_cast checks, at runtime, that you "guessed" right

Note: simplified, as dynamic_cast also allows cross-casts and casts involving virtual bases.

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

  • if the target is a reference (ie dynamic_cast<T&>(u)), then if the check fails dynamic_cast throws a std::bad_cast exception
  • if the target is a pointer (ie dynamic_cast<T*>(p)), then if the checks fails 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 full object

In this case, you may:

  • switch from dynamic_cast<NonPlayableCharacter*>(_allChar[0])->getNPCState() to dynamic_cast<NonPlayableCharacter&>(*_allChar[0]).getNPCState(), and let the exception propagates
  • test the result of the cast (NonPlayableCharacter* test here) for non-nullity
like image 156
Matthieu M. Avatar answered Sep 23 '22 02:09

Matthieu M.