Повторите десять раз - единственное, что вы можете безопасно сделать с указателем reinterpret_cast
, это reinterpret_cast
вернуть его к тому же типу указателя, с которого он пришел. То же самое относится к преобразованиям в void*
: необходимо преобразовать обратно в исходный тип.
Итак, если вы разыгрываете DecoratedSquare*
на void*
, вы должны вернуть его на DecoratedSquare*
. Не Decorated*
, не Square*
, не Shape*
. Некоторые из них могут работать на вашем компьютере, но это сочетание удачи и поведения, зависящего от реализации. Обычно он работает с единичным наследованием, потому что нет очевидной причины для реализации указателей объектов таким образом, чтобы это прекратило работать, но это не гарантировано, и это не может работать вообще для множественного наследования.
Вы говорите, что ваш код обращается к "произвольным типам, включая примитивные типы" через void *. В этом нет ничего плохого - по-видимому, тот, кто получает данные, знает, что к ним следует обращаться как DecoratedSquare*
, а не как, скажем, int*
.
Если тот, кто получает его, знает, что он должен обращаться с ним как с базовым классом, таким как Decorated*
, то тот, кто преобразует его в void*
, должен сначала static_cast
преобразовать его в базовый класс, затем в void*
:
void *decorated_vp = static_cast<Decorated*>(ds);
Теперь, когда вы приведете decorated_vp
обратно к Decorated*
, вы получите результат static_cast<Decorated*>(ds)
, который вам нужен.