My question is, how does this work, if it does?
It doesn't, at least not in any well-defined manner. Trying to do anything with a destroyed non-trivial object gives undefined behaviour.
It's possible that, on some particular implementation, the cast might fail cleanly if the object's been destroyed. But it's just as likely to crash or order pizza.
There are various ways to make sure an object is valid before use - such as smart pointers, or well-structured scopes - but testing the object itself (whether by RTTI or user-declared member data) will not work, since the object can't safely be accessed after destruction.
Does dynamic_cast
still do something if the start and end types are the same?
It might do nothing, since it can assume that the pointer is valid, and therefore that the cast will succeed. Or it might do a run-time type check anyway, which will succeed if the pointer is valid, and give undefined behaviour otherwise.
Could there be any point to a dynamic cast to the same exact type or is that likely just "bad" code?
No, there's no point. Either the pointer already points to a valid object of the correct type, in which case you can just use it; or it doesn't, in which case dynamic_cast
is undefined.