Использование static_cast нормально в этом примере, но reinterpret_cast - нет.Потому что reinterpret_cast не конвертирует vtable.
Нет, проблема в том, что reinterpret_cast
полностью забывает о наследовании.Он просто вернет тот же адрес без изменений 1 .Но static_cast
знает , что вы выполняете понижение: то есть приведение из базового класса к производному классу.Поскольку он знает оба задействованных типа, он соответствующим образом корректирует адрес, т. Е. Делает правильные вещи.
Давайте притворимся наша реализация выкладывает гипотетический класс OVERLAPPEDEX
, который имеет виртуальную функцию, подобную этой:
+------+------------+------------------+-------------+
| vptr | OVERLAPPED | AssociatedClient | ClientState |
+------+------------+------------------+-------------+
^
|
ptr
Указатель, который нам дан, указывает на подобъект OVERLAPPED
.reinterpret_cast
не изменит это.Это только изменило бы тип.Очевидно, что доступ к классу OVERLAPPEDEX
через этот адрес может привести к хаосу, потому что расположение его подобъектов теперь совершенно неверно!
what we believe we have when we access OVERLAPPEDEX through the pointer
+------+------------+------------------+-------------+
| vptr | OVERLAPPED | AssociatedClient | ClientState |
+------+------+-----+------+-----------+------+------+------+
| vptr | OVERLAPPED | AssociatedClient | ClientState | <- what we actually have
+------+------------+------------------+-------------+
^
|
ptr
static_cast
знает , что для преобразованияOVERLAPPED*
до OVERLAPPEDEX*
он должен корректировать адрес и делает правильные вещи:
+------+------------+------------------+-------------+
| vptr | OVERLAPPED | AssociatedClient | ClientState |
+------+------------+------------------+-------------+
^
|
ptr after static_cast
Хотя, если я использую там C-Style приведение (не reinterpret_cast),может ли это также пойти не так?
Приведение в стиле C определяется как первое из следующих успешных:
const_cast
static_cast
static_cast
, затем const_cast
reinterpret_cast
reinterpret_cast
, затем const_cast
Asвы можете видеть, что static_cast
пробуется раньше reinterpret_cast
, поэтому в этом случае приведение в стиле C также будет делать правильные вещи.
Подробнее
1 Не гарантируется.Существует очень мало гарантий относительно того, что происходит на reinterpret_cast
.Все известные мне реализации просто выдадут один и тот же адрес без изменений.