Большую часть времени вам вообще не следует кастовать.
B bInst
A * myInst = &bInst;
A* getA() { return &bInst; }
B* getB() { return &bInst; }
Simples!
Есть редкие случаи, когда вам нужно бросить иерархию. Обычно здесь вы загружаете какое-то дополнение и должны проверить, что объект того типа, который вы ожидаете. В этом случае вы используете dynamic_cast <> для проверки, но должны иметь RTTI.
Другой случай возникает, когда у вас есть хранилище несвязанных типов, например, вариантов / «любых» типов, которые связаны только тем фактом, что они хранятся вместе в одной коллекции, и, вероятно, обрабатываются по-разному после извлечения. Это также может произойти в конечном автомате. Хотя может быть возможно спроектировать ваш поток здесь, чтобы избежать бросков, иногда приведение проще. В таком случае вы точно знаете, какой у вас тип, и можете static_cast перейти по иерархии до него.