2010-07-25 2 views
6

Se si dispone di un void * puntatore alla classe derivata che eredita da entrambi BaseA e BaseB, come fa il compilatore il cast del puntatore void* a BaseA* (o BaseB*) senza sapere che il puntatore void* è di tipo Derived?Casting con l'ereditarietà multipla

risposta

5

Non funziona. L'unica garanzia quando lancia in e da una void* utilizzando un static_cast è:

Un valore di tipo puntatore di opporsi convertito in "puntatore a cv void" e ritorna al tipo di puntatore originale avrà il suo valore originale (C + +03 §5.2.9/10).

Ad esempio, il codice seguente è corretto poiché il void* è gettata a un tipo diverso dal tipo puntatore originale (la sequenza cast è 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); 

tentativo utilizzare b2ptr qui comporterebbe un comportamento indefinito. L'unico tipo con il quale è possibile trasmettere in modo sicuro voidptr è B1*, poiché questo è il tipo da cui è stato ottenuto il valore (bene, o su un valore char*, poiché è possibile accedere a qualsiasi elemento tramite char*).

3

Il compilatore non lancia il puntatore void* su qualsiasi cosa: tu, il programmatore, fai.

Al fine di fare qualcosa di utile con un puntatore void*, è necessario esplicitamente cast a un puntatore non void*, e se ti sbagli su ciò che digitare il puntatore in realtà indica, si entra Non definito Comportamento Città .

+0

La tua risposta è corretta. Dalla mia ricerca se Derived estende BaseA e BaseB, l'oggetto è disposto in memoria come | BaseA | BaseB | Derivato |. Quindi il puntatore punta verso l'inizio di BaseA, quindi il cast di Derivati ​​in BaseB ti farà leggere i membri di BaseA. – Chazz