c++ rtti void-pointers dynamic-cast

c++ - dynamic_cast desde "void*"



rtti void-pointers (5)

De acuerdo con this , void* no tiene información RTTI, por lo tanto, la conversión desde void* no es legal y tiene sentido.

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

¿Puedes aclarar el problema?


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

  • 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 lvalue de un tipo de clase completo (gracias usta por comentar sobre mi omisión)

...

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

Entonces, no, un (void*) no está permitido.

Pensemos en lo que podría significar su solicitud: digamos que tiene un puntero que es realmente un Derived1* , pero el código dynamic_cast -ing solo sabe que es un void* . Supongamos que intenta convertirlo en 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 al 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 la clase Base necesario puede no ser el Derived* el Derived* , disponible solo como un 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 sobre la necesidad de que el puntero desde el que está lanzando sea de tipo polimórfico, que tenga funciones virtuales. Todo eso es válido, pero un poco engañoso. Como puede ver arriba, incluso si el void* es a tal escribirlo todavía no funcionaría de manera confiable sin la información de tipo completo, ya que el problema real es que el void* está presuntamente apuntando al inicio del objeto derivado, mientras que se necesita un puntero al subobjeto de la clase base desde el cual para escribir deriva.)


Es cierto que void* no se puede dynamically_cast desde.

Probablemente estés 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); }

Obtuve el siguiente error:

can not dynamic_cast ''p'' (de tipo ''void *'') para escribir ''struct A *'' (la fuente no es un puntero a la clase)


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


Supongo que confundirás con dynalic_cast para void* . Eso es legal y obtiene el puntero al objeto de clase más derivado.

dynamic_cast from void* es ilegal - el tipo creado debe ser polimórfico - contiene al menos una función virtual (el destructor virtual cuenta también).


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

En gcc puedes hacer dynamic_cast a void* pero no desde :

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 }