trilingue poliglota online complutense biblia bac c++ casting rtti dynamic-cast

c++ - bac - biblia poliglota complutense online



¿Cuáles son algunos ejemplos de "buen uso" de fundición dinámica? (6)

A menudo escuchamos / leemos que uno debe evitar el casting dinámico. Me preguntaba cuáles serían los ejemplos de "buen uso" de eso, según usted.

Editar:

Sí, estoy al tanto de ese otro hilo : de hecho, al leer una de las primeras respuestas, hice mi pregunta.


Aquí hay algo que hago a menudo, no es bonito, pero es simple y útil.

A menudo trabajo con contenedores de plantillas que implementan una interfaz, imagino algo así como

template<class T> class MyVector : public ContainerInterface ...

Donde ContainerInterface tiene elementos básicos útiles, pero eso es todo. Si quiero un algoritmo específico en vectores de enteros sin exponer la implementación de mi plantilla, es útil aceptar los objetos de interfaz y dynamic_cast hacia abajo a MyVector en la implementación. Ejemplo:

// function prototype (public API, in the header file) void ProcessVector( ContainerInterface& vecIfce ); // function implementation (private, in the .cpp file) void ProcessVector( ContainerInterface& vecIfce) { MyVector<int>& vecInt = dynamic_cast<MyVector<int> >(vecIfce); // the cast throws bad_cast in case of error but you could use a // more complex method to choose which low-level implementation // to use, basically rolling by hand your own polymorphism. // Process a vector of integers ... }

Podría agregar un método Process () a ContainerInterface que se resolvería polimórficamente, sería un método OOP más agradable, pero a veces prefiero hacerlo de esta manera. Cuando tiene contenedores simples, muchos algoritmos y quiere mantener su implementación oculta, dynamic_cast ofrece una solución fácil y fea.

También puede ver las técnicas de envío doble.

HTH


Bueno, realmente sería bueno con los métodos de extensión en C #.

Por ejemplo, digamos que tengo una lista de objetos y quiero obtener una lista de todos los id. Puedo recorrerlos todos y sacarlos, pero me gustaría segmentar ese código para su reutilización.

algo así como

List<myObject> myObjectList = getMyObjects(); List<string> ids = myObjectList.PropertyList("id");

Sería genial, excepto en el método de extensión que no sabrá el tipo que está entrando.

Asi que

public static List<string> PropertyList(this object objList, string propName) { var genList = (objList.GetType())objList; }

sería grandioso.


Es muy útil, sin embargo, la mayoría de las veces es demasiado útil: si para hacer el trabajo de la manera más fácil es hacer un dynamic_cast, a menudo es un síntoma de un mal diseño de OO, lo que a su vez puede conducir a problemas en el futuro de formas imprevistas.


Este hilo reciente da un ejemplo de lo que es útil. Hay una clase base de Shape y las clases Circle y Rectangle derivadas de ella. Al probar la igualdad, es obvio que un Círculo no puede ser igual a un Rectángulo y sería un desastre intentar compararlos. Mientras itera a través de una colección de punteros a Shapes, dynamic_cast hace doble función, diciéndole si las formas son comparables y le da los objetos adecuados para hacer la comparación.

Vector iterator no referenciable


Mi proyecto actual de juguetes usa dynamic_cast dos veces; una vez para solucionar la falta de despacho múltiple en C ++ (es un sistema de estilo visitante que podría usar el envío múltiple en lugar de los dynamic_casts), y una vez para un caso especial un subtipo específico.

Ambas son aceptables, en mi opinión, aunque la primera al menos se debe a un déficit de idioma. Creo que esta puede ser una situación común, de hecho; la mayoría de los dynamic_casts (y una gran cantidad de "patrones de diseño" en general) son soluciones para fallas de lenguaje específicas en lugar de algo que pretenden.


Se puede usar para un poco de seguridad de tipo en tiempo de ejecución cuando se exponen manejadores a objetos a través de una interfaz C. Haga que todas las clases expuestas hereden de una clase base común. Cuando acepte un manejador de una función, primero realice el lanzamiento a la clase base, luego realice un lanzamiento dinámico a la clase que está esperando. Si pasaron en un manejador no sensitivo, obtendrás una excepción cuando el tiempo de ejecución no pueda encontrar el rtti. Si pasan un identificador válido del tipo incorrecto, obtienes un puntero NULL y puedes lanzar tu propia excepción. Si pasaron en el puntero correcto, estás listo para ir. Esto no es a prueba de tontos, pero sin duda es mejor para detectar llamadas erróneas a las bibliotecas que un molde de reinterpretación directa desde un identificador, y esperar hasta que algunos datos se corrompen misteriosamente cuando se pasa el identificador incorrecto.