std::bad_cast
выбрасывается при приведении ссылки
С приведением указателя, как вы упомянули, вы можете использовать dynamic_cast
Base* b = dynamic_cast<Base*>(a); // could return nullptr
Со ссылкой вы не можете назначить nullptr
try
{
Base& b = dynamic_cast<Base&>(a);
}
catch(const std::bad_cast& e)
{
std::cout << e.what() << '\n';
}
, поэтому std::bad_cast
предоставляет механизм, позволяющий узнать, что приведение не выполнено.