dynamic_cast только подтвердит ваше предположение, и даже это не идеально. Если C наследует от B, который наследует от A, dynamic_cast<B*>((A*)&theC)
будет работать. typeid
даст вам фактический тип, но в некотором смысле это не совсем полезно для чего-либо. Например, вы не можете создавать новые объекты того же типа.
Итак, остаётся вопрос о том, какова ваша настоящая цель. При правильном проектировании ОО вам никогда не нужно знать о неограниченном наборе типов, которые могут быть получены из базового типа.