2010-11-09 16 views
30

Según this, void* no tiene información de RTTI, por lo tanto, la fundición de void* no es legal y que tenga sentido.dynamic_cast de "void *"

Si no recuerdo mal, dynamic_cast de void* estaba trabajando en gcc.

Puede aclarar el problema.

Respuesta

35

dynamic_cast sólo funciona en tipos polimórficos, clases es decir que contienen funciones virtuales.

En gcc se puede dynamic_castavoid* pero no de:

struct S 
{ 
    virtual ~S() {} 
}; 

int main() 
{ 
    S* p = new S(); 
    void* v = dynamic_cast<void*>(p); 
    S* p1 = dynamic_cast<S*>(v); // gives an error 
} 
3

Es cierto que void* no puede ser dynamically_cast ed from.

Probablemente esté recordando mal. Con g ++ 4.5 y el siguiente código

struct A { 
    virtual ~A(); 
}; 

int main() { 
    A a; 
    void *p = &a; 
    A* pa = dynamic_cast<A*>(p); 
} 

me sale el siguiente error:

cannot dynamic_cast 'p' (of type 'void*') to type 'struct A*' (source is not a pointer to class)

0

supongo que confundir con dynalic_castavoid*. Eso es legal y obtiene el puntero al objeto de clase más derivado.

dynamic_castdevoid* es ilegal - el tipo fundido desde debe ser polimórfico - contener al menos una función virtual (recuentos destructor virtual también).

+0

A menos que el tipo de clase casted to sea una clase base accesible inequívoca del tipo de clase de la expresión fundida, en cuyo caso este último no necesita ser poli mórfico – usta

0

Puede convertir un puntero al tipo polimórfico en void *, pero no al revés.

11

En 5.2.7 - Dynamic cast [expr.dynamic.cast] dice que para dynamic_cast<T>(v):

  • Si T es un tipo de puntero, v a bordo otro valor p de un puntero para completar tipo de clase
  • Si T es un tipo de referencia, v será un lvalue de un tipo de clase completo (gracias usta para comentar sobre mi falta esto)

...

  • De lo contrario, v será un puntero a un valor-I o de un tipo polimórfico

Así que no, un valor (void*) no está permitido.

Vamos a pensar en lo que podría significar su solicitud: Digamos que tienes un puntero que es realmente a un Derived1*, pero el código dynamic_cast -ing sólo sabe que es un void*.Supongamos que intenta convertirlo a Derived2*, donde ambas clases derivadas tienen una base común. Superficialmente, podría pensar que todos los punteros apuntarían al mismo objeto Base, que contendría un puntero a la tabla de despacho virtual relevante y RTTI, para que todo pueda colgarse. Sin embargo, tenga en cuenta que las clases derivadas pueden tener múltiples clases base y, por lo tanto, el subobjeto de clase Base necesario podría no ser aquel al que apunta el Derived*, disponible solo como void*. No funcionaria Conclusión: el compilador necesita conocer estos tipos para poder realizar algunos ajustes en los punteros en función de los tipos involucrados.

 
Derived1* -----> [AnotherBase] 
       [[VDT]Base] <-- but, need a pointer to start of 
       [extra members] this sub-object for dynamic_cast 

(Algunas respuestas hablan de la necesidad de que el puntero está fundición de ser de un tipo polimórfico, que tiene funciones virtuales. Eso es lo único válido, pero un poco engañoso. Como se puede ver arriba, incluso si el void* es de ese tipo, aún no funcionaría de manera confiable sin la información de tipo completo, ya que el problema real es que void* presuntamente apunta al inicio del objeto derivado, mientras que se necesita un puntero al subobjeto de la clase base de donde deriva el tipo fundido.)

+0

Si T es un tipo de puntero, v será un valor de r de un puntero para completar el tipo de clase, ... Si T es un tipo de referencia, v será un valor l de un tipo de clase completo, ... – usta

+1

@usta: fijo , Gracias. –