Если у вас есть пустое * указатель на производный класс, который наследует от обоих BaseA
и BaseB
, как компилятор бросил void*
указатель на BaseA*
(или BaseB*
), не зная, что void*
указатель типа Derived
?Кастинг с множественным наследованием
ответ
Это не так. Единственной гарантией при литье в и из void*
с использованием static_cast
является:
Значение указателя типа на объект преобразуется в «указатель на
cv void
» и обратно к первоначальному типу указателя будет иметь свое первоначальное значение (С + +03 §5.2.9/10).
Например, следующий код неверен, потому что void*
отливают типа, отличные от исходного типа указателя (последовательность приведения B1*
->void*
->B2*
):
struct B1 { int i; };
struct B2 { int j; };
struct D : B1, B2 { };
D x;
B1* b1ptr = &x;
void* voidptr = b1ptr;
B2* b2ptr = static_cast<B2*>(voidptr);
Попытка использование b2ptr
приведет к неопределенному поведению. Единственным типом, который можно безопасно отличить voidptr
, является B1*
, так как это тот тип, из которого был получен void*
(ну или char*
, так как все можно получить через char*
).
Компилятор не использует указатель void*
на что угодно - вы, программист, делаете.
Для того, чтобы сделать что-нибудь полезное с void*
указателем, вам нужно в явном виде приводите его к не- void*
указатель, и если вы не правы о том, что тип указателя на самом деле указывает на, вы вступаете Неопределенное поведение Город ,
Ваш ответ верный. Из моего исследования, если Derived расширяет BaseA и BaseB, объект выкладывается в память как | BaseA | BaseB | Derived |. Таким образом, указатель указывает на начало BaseA, поэтому при отливке Derived to BaseB вы будете читать элементы BaseA. – Chazz