2010-07-25 20 views
6

Si usted tiene un void * puntero a la clase derivada que se hereda de ambos BaseA y BaseB, ¿cómo el compilador del puntero de void* a BaseA* (o BaseB*) sin saber que el puntero void* es de tipo Derived?casting con la herencia múltiple

Respuesta

5

No es así. La única garantía cuando se lanza hacia y desde un void* usando un static_cast es:

Un valor de tipo puntero a objeto convertido a "puntero a cv void" y de nuevo al tipo de puntero original, tendrá su valor original (C + +03 §5.2.9/10).

Por ejemplo, el siguiente código es incorrecto porque el void* es echado a un tipo distinto del tipo de puntero original (la secuencia de reparto es 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); 

Intentando usar b2ptr aquí daría como resultado un comportamiento indefinido. El único tipo al que puede emitir voidptr de forma segura es B1*, ya que ese es el tipo del que se obtuvo el void* (bueno, o en un char*, ya que se puede acceder a cualquier cosa mediante un char*).

3

El compilador no arroja el puntero void* a nada, usted, el programador, do.

Con el fin de hacer algo útil con un puntero void*, es necesario explícitamente echarlo a un puntero no void*, y si se equivoca en lo que escriba el puntero señala realmente a, introduce Indefinido Comportamiento City .

+0

Tu respuesta es correcta. De mi investigación si Derived amplía BaseA y BaseB, el objeto se presenta en la memoria como | BaseA | BaseB | Derived |. Por lo tanto, el puntero apunta al inicio de BaseA, por lo que la conversión derivada a BaseB hará que usted lea los miembros de BaseA. – Chazz