How to safely cast_to when checking if X is Y?

:information_source: Attention Topic was automatically imported from the old Question2Answer platform.
:bust_in_silhouette: Asked By MXXIV

I have this code, with the intent of handling what happens a projectile hits something that can be shot. In my project, Projectile inherits RigidBody2D, and the targets inherit Shootable which also inherits RigidBody2D.

  TypedArray<Node2D> colliders = get_colliding_bodies();
  bool hit = false;
  for (int i=0; i<colliders.size(); ++i)
  {
    Object* o = colliders[i];

    if (PhysicsBody2D* body = Object::cast_to<PhysicsBody2D>(o))
    {
      if (ShootableObject* shootable = Object::cast_to<ShootableObject>(body))
      {
        if (shootable == nullptr)
        {
          throw std::runtime_error("cast_to produced nullptr!");
        }

        if(shootable->is_inside_tree())
          shootable->receiveDamage(props.damage);
      }
      hit = true;
    }
  }

  if (hit)
  {
    queue_free();
  }

The problem is it appears this is not the correct way to do it. This part:

ShootableObject* shootable = Object::cast_to<ShootableObject>(body)

Always returns a pointer, even if I am casting something that is not Shootable. So how can I correctly check what has been hit and react based on that?