Использование static_cast в порядке, но reinterpret_cast - нет. Поскольку reinterpret_cast не конвертирует vtable.
Нет, проблема в том, что reinterpret_cast
совершенно не обращает внимания на наследование. Он просто вернет тот же адрес без изменений . Но static_cast
знает, что вы выполняете downcast: т. Е. Отбрасываете базовый класс на производный класс. Поскольку он знает оба типа, он соответствующим образом корректирует адрес, т. Е. Делает правильные вещи.
Давайте притвориться наша реализация выкладывает гипотетический 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
Как вы можете видеть, static_cast
проверялся перед reinterpret_cast
, поэтому в данном случае, C-стиль литая также делать правильные вещи.
More info
не гарантируется. Есть очень мало гарантий относительно того, что происходит на reinterpret_cast
. Все реализации, о которых я знаю, просто выдадут один и тот же адрес без изменений.
Я вообще не разбираюсь в C++, но я понимаю, что «реинтерпрет-литье» означает именно то, что '* (destination_type *) &' будет означать в C. Предположительно «статический бросок» фактически принимает классовые отношения в и позволяет компилятору выполнять нетривиальное преобразование. –