Есть в C++ такая штука, как неопределённость приводимости типа в случае ромбовидного наследования:
struct A {};
struct I1 : public A {};
struct I2 : public A {};
struct B : public I1, public I2 {};
int main()
{
B *b = new B();
A *a = b; // error: ambiguous conversions from 'B *' to 'A *'
A *a = reinterpret_cast<A *>(b); // OK
return 0;
}
Ошибку сообщает компилятор, и она может решаться грубой силой - через reinterpret_cast.
Но компилятор ничего не скажет в случае подразумеваемого приведения:
try
{
throw new B();
}
catch(A *a)
{
// ожидаем попасть сюда, но фигушки!
delete a;
}
catch(void *e)
{
// мы сюда попадём
delete e;
}
В результате можно напороться на очень неожиданное поведение. Особенно если исключения не протестированы.
Мораль:
1) Не увлекаться наследованиями, особенно множественными, особенно с ромбовидной структурой иерархии.
2) Если невозможно, то управлять соответствием типов при помощи конструкций reinterpret_cast<A *>(new B()) и т.п.
3) Не передавать через механизм обработки исключений чего ни попадя, ограничиваясь специально созданными для этого классами и их объектами.