Если вы напишите этот код более четко, вам будет легче увидеть, что идет не так:
void * addr = std::malloc(LARGE_NUMBER);
Base * b = new (addr) Base;
b->foo(); // no problem
Derived * d = new (addr) Derived;
d->bar(); // also fine (#1)
b->foo(); // Error! b no longer points to a Base!
static_cast<Base*>(d)->foo(); // OK
b = d; b->foo(); // also OK
Проблема в том, что в строке, отмеченной (# 1), b
и d
точкана совершенно разные, не связанные между собой вещи, и поскольку вы перезаписали память прежнего объекта *b
, b
фактически больше не действует вообще.
У вас могут возникнуть некоторые ошибочные мысли о Base*
иDerived*
являются конвертируемыми типами указателей, но это не имеет ничего общего с существующей ситуацией, и ради этого примера оба типа также могут быть совершенно не связаны между собой.Только в одной из последних двух строк мы используем тот факт, что Derived*
конвертируется в Base*
, когда мы выполняем фактическое преобразование.Но обратите внимание, что это преобразование является подлинным значением преобразования, и d
- это не тот же указатель , что и static_cast<Base*>(d)
(по крайней мере, в том, что касается языка).
Наконец, давайте исправим этот беспорядок:
d->~Derived();
std::free(addr);
Возможность уничтожить оригинал *b
упущена, поэтому мы могли это просочиться.