¿Cuál es el método preferido para lograr el equivalente en C ++ de Java instanceof
?
java
c++
oop
instanceof
Yuval Adam
fuente
fuente
Respuestas:
Intenta usar:
Esto requiere que su compilador tenga habilitado el soporte rtti.
EDITAR: ¡He tenido algunos buenos comentarios sobre esta respuesta!
Cada vez que necesite usar un dynamic_cast (o una instancia de), será mejor que se pregunte si es algo necesario. Generalmente es una señal de mal diseño.
Las soluciones típicas son poner el comportamiento especial para la clase que está comprobando en una función virtual en la clase base o tal vez introducir algo como un visitante donde puede introducir un comportamiento específico para las subclases sin cambiar la interfaz (excepto para agregar la interfaz de aceptación del visitante de curso).
Como se señaló, dynamic_cast no viene gratis. Un truco simple y de rendimiento constante que maneja la mayoría (pero no todos los casos) es básicamente agregar una enumeración que represente todos los tipos posibles que su clase puede tener y verificar si obtuvo el correcto.
Este no es un buen diseño, pero puede ser una solución alternativa y su costo es más o menos solo una llamada de función virtual. También funciona independientemente de que RTTI esté habilitado o no.
Tenga en cuenta que este enfoque no admite múltiples niveles de herencia, por lo que si no tiene cuidado, puede terminar con un código como este:
fuente
Dependiendo de lo que quieras hacer, podrías hacer esto:
Utilizar:
Sin embargo, esto opera únicamente en los tipos conocidos por el compilador.
Editar:
Este código debería funcionar para punteros polimórficos:
Ejemplo: http://cpp.sh/6qir
fuente
Instancia de implementación sin Dynamic_cast
Creo que esta pregunta sigue siendo relevante hoy. Usando el estándar C ++ 11 ahora puede implementar una
instanceof
función sin usardynamic_cast
así:Pero aún depende del
RTTI
soporte. Así que aquí está mi solución para este problema dependiendo de algunas Macros y Metaprogramming Magic. El único inconveniente es que este enfoque no funciona para la herencia múltiple .InstanceOfMacros.h
Manifestación
Luego puede usar estas cosas ( con precaución ) de la siguiente manera:
DemoClassHierarchy.hpp *
El siguiente código presenta una pequeña demostración para verificar el comportamiento correcto rudimentario.
InstanceOfDemo.cpp
Salida:
Actuación
La pregunta más interesante que surge ahora es si estas cosas malvadas son más eficientes que el uso de
dynamic_cast
. Por lo tanto, he escrito una aplicación de medición de rendimiento muy básica.InstanceOfPerformance.cpp
Los resultados varían y se basan esencialmente en el grado de optimización del compilador. Compilar el programa de medición de rendimiento utilizando
g++ -std=c++11 -O0 -o instanceof-performance InstanceOfPerformance.cpp
la salida en mi máquina local fue:Mhm, este resultado fue muy aleccionador, porque los tiempos demuestran que el nuevo enfoque no es mucho más rápido en comparación con el
dynamic_cast
enfoque. Es incluso menos eficiente para el caso de prueba especial que prueba si un puntero deA
es una instancia deA
. PERO la marea cambia ajustando nuestro binario usando la compilación otpimization. El comando del compilador respectivo esg++ -std=c++11 -O3 -o instanceof-performance InstanceOfPerformance.cpp
. El resultado en mi máquina local fue sorprendente:Si no depende de la herencia múltiple, no se opone a las viejas macros C, RTTI y metaprogramación de plantillas y no es demasiado vago para agregar algunas pequeñas instrucciones a las clases de su jerarquía de clases, entonces este enfoque puede impulsar un poco su aplicación con respecto a su rendimiento, si a menudo termina comprobando la instancia de un puntero. Pero úsalo con precaución . No hay garantía para la corrección de este enfoque.
Nota: Todas las demostraciones se compilaron utilizando
clang (Apple LLVM version 9.0.0 (clang-900.0.39.2))
macOS Sierra en una MacBook Pro Mid 2012.Editar: También probé el rendimiento en una máquina Linux usando
gcc (Ubuntu 5.4.0-6ubuntu1~16.04.9) 5.4.0 20160609
. En esta plataforma, el beneficio de rendimiento no fue tan significativo como en macOs con clang.Salida (sin optimización del compilador):
Salida (con optimización del compilador):
fuente
dynamic_cast
Se sabe que es ineficiente. Atraviesa la jerarquía de herencia, y es la única solución si tiene múltiples niveles de herencia, y necesita verificar si un objeto es una instancia de cualquiera de los tipos en su jerarquía de tipos.Pero si una forma más limitada de
instanceof
eso solo verifica si un objeto es exactamente del tipo que especifique, es suficiente para sus necesidades, la función a continuación sería mucho más eficiente:Aquí hay un ejemplo de cómo invocaría la función anterior:
Debería especificar el tipo de plantilla
A
(como el tipo que está buscando) y pasar el objeto que desea probar como argumento (a partir del cualK
se deduciría el tipo de plantilla ).fuente
fuente
instanceof
consulta el tipo dinámico, pero en esta respuesta el tipo dinámico y estático siempre se corresponden.Esto funcionó perfecto para mí usando Code :: Blocks IDE con GCC complier
fuente
typeid
", que si bien es incorrecta ("No hay garantía de que todas las evaluaciones de la expresión typeid en el mismo tipo ...assert(typeid(A) == typeid(A)); /* not guaranteed */
" hagan referencia a la misma instancia std :: type_info ), vea cppreference.com ), indica que al menos trató de responder la pregunta, si no fue útil porque se olvidó de ofrecer un ejemplo de trabajo mínimo.