2012-01-06 14 views
13

¿Qué ventajas inherentes ofrecen boost::any y boost::any_cast durante el uso de void* y dynamic_cast?¿Por qué `boost :: any` es mejor que` void * `?

+9

No se puede 'dynamic_cast' from' void * ' –

+0

@ArmenTsirunyan Siempre pensé que era posible hacerlo, aunque nunca lo intenté ...: | –

+1

@PaulManta con respecto al comentario de Armen, usted puede echar un vistazo a esta pregunta http://stackoverflow.com/questions/6771998/dynamic-cast-of-void –

Respuesta

21

La ventaja es que boost::any es mucho más seguro que void*.

E.g.

int i = 5; 
void* p = &i; 
static_cast<double*>(p); //Compiler doesn't complain. Undefined Behavior. 
boost::any a; 
a = i; 
boost::any_cast<double>(a); //throws, which is good 

En cuanto a su comentario, no se puede dynamic_cast de un void*. Puede dynamic_cast sólo de punteros y referencias a los tipos de clases que tienen al menos una función virtual (tipos aka polimórficas)

+0

Sí, pero eso es un elenco estático, no dinámico emitir.Tu comentario de que no puedes usar 'dynamic_cast' en' void * 'fue una mejor respuesta. ¿O fue su punto de que no hay nada que le impida usar 'static_cast' aunque no debería? :) –

+0

@Paul: Agregué esa parte a mi respuesta –

5

Esto es lo que se referencia impulso dice:

Es compatible con la copia de cualquier tipo de valor y seguro comprobado extracción de que valor estrictamente contra su tipo.

Ninguno de estos se puede hacer con un void*. No hay cheques para ti y tienes que saber a ti mismo a qué puedes recurrir.

No creo que dynamic_cast entre en la imagen, ya que no tiene nada que ver con ninguno de los dos.

13

boost::any llamadas destructores:

{ 
    boost::any x = std::string("Hello, world"); 
    x = std::wstring(L"Goodbye"); // string::~string called here 
} // wstring::~wstring called here 
6

alguna manera nadie mencionó que cualquier impulso :: <> actúa como un tipo de valor, donde como void * es un puntero. Eso significa que cualquier <> puede almacenar CUALQUIER objeto de CUALQUIER tamaño. Una vez almacenado, puede pasar la variable de cualquier <> escriba en cualquier lugar que desee; vive por sí mismo.

Por otro lado, void * tiene el tamaño del puntero, por lo que debe asegurarse de que sizeof (sus datos) < = sizeof (void *) o su vacío * sea solo un puntero a los datos reales almacenados en algún otro lugar. Pero en ese caso, es completamente diferente de cualquier <> porque ahora necesita preocuparse por eso "en otro lugar" y asegurarse de que siga siendo válido siempre que void * sea válido, lo que a veces podría convertirse en un desafío, especialmente en aplicaciones multiproceso .

Además de lo que otros han mencionado, <> es muy seguro, almacenará todo lo que desee, pero la única manera de recuperarlo es saber el tipo exacto o falla (lo que puede ser molesto cuando uno API le da unsigned int y su código quiere int se tratan como tipos diferentes). void * te permitirá hacer lo que quieras con él y si comienzas a leer o pavimentar sobre montón y/o memoria no inicializada, no te detendrá ni siquiera te hará saber que lo estás haciendo.

Cuestiones relacionadas