¿Por qué C ++ no tiene reflejo?

337

Esta es una pregunta un tanto extraña. Mis objetivos son comprender la decisión del diseño del lenguaje e identificar las posibilidades de reflexión en C ++.

  1. ¿Por qué el comité de lenguaje C ++ no se dirigió a implementar la reflexión en el lenguaje? ¿Es la reflexión demasiado difícil en un lenguaje que no se ejecuta en una máquina virtual (como Java)?

  2. Si uno implementara la reflexión para C ++, ¿cuáles serían los desafíos?

Supongo que los usos de la reflexión son bien conocidos: los editores se pueden escribir más fácilmente, el código del programa será más pequeño, se pueden generar simulacros para pruebas unitarias, etc. Pero sería genial si pudieras comentar sobre los usos de la reflexión también.

amit
fuente

Respuestas:

631

Hay varios problemas con la reflexión en C ++.

  • Es mucho trabajo agregar, y el comité de C ++ es bastante conservador, y no dedique tiempo a nuevas características radicales a menos que estén seguros de que valdrá la pena. (Se ha hecho una sugerencia para agregar un sistema de módulos similar a los ensamblados .NET, y aunque creo que existe un consenso general de que sería bueno tenerlo, no es su máxima prioridad en este momento, y se ha retrasado hasta mucho después C ++ 0x. La motivación de esta característica es deshacerse del #includesistema, pero también permitiría al menos algunos metadatos).

  • No pagas por lo que no usas. Esa es una de las filosofías de diseño básicas que subyacen a C ++. ¿Por qué mi código debe llevar metadatos si nunca lo necesito? Además, la adición de metadatos puede inhibir la optimización del compilador. ¿Por qué debería pagar ese costo en mi código si es posible que nunca necesite esos metadatos?

  • Lo que nos lleva a otro gran punto: C ++ ofrece muy pocas garantías sobre el código compilado. El compilador puede hacer casi todo lo que quiera, siempre que la funcionalidad resultante sea la esperada. Por ejemplo, no se requiere que sus clases estén realmente allí . El compilador puede optimizarlos, alinear todo lo que hacen, y con frecuencia hace exactamente eso, porque incluso el código de plantilla simple tiende a crear bastantes instancias de plantilla. La biblioteca estándar de C ++ se basa en esta optimización agresiva. Los functores solo son efectivos si la sobrecarga de instanciar y destruir el objeto puede optimizarse. operator[]en un vector solo es comparable a la indexación de matriz cruda en rendimiento porque todo el operador puede alinearse y, por lo tanto, eliminarse por completo del código compilado. C # y Java ofrecen muchas garantías sobre la salida del compilador. Si defino una clase en C #, esa clase existirá en el ensamblaje resultante. Incluso si nunca lo uso. Incluso si todas las llamadas a sus funciones miembro pudieran estar en línea. La clase tiene que estar allí, para que la reflexión pueda encontrarla. Parte de esto se alivia compilando C # en bytecode, lo que significa que el compilador JIT puedeelimine las definiciones de clase y las funciones en línea si lo desea, incluso si el compilador inicial de C # no puede. En C ++, solo tiene un compilador, y tiene que generar un código eficiente. Si se le permitiera inspeccionar los metadatos de un ejecutable de C ++, esperaría ver todas las clases que definió, lo que significa que el compilador tendría que preservar todas las clases definidas, incluso si no son necesarias.

  • Y luego están las plantillas. Las plantillas en C ++ no se parecen en nada a los genéricos en otros lenguajes. Cada instanciación de plantilla crea un nuevo tipo. std::vector<int>es una clase completamente separada de std::vector<float>. Eso se suma a muchos tipos diferentes en un programa completo. ¿Qué debería ver nuestra reflexión? La plantilla std::vector ? Pero, ¿cómo puede hacerlo, ya que es una construcción de código fuente, que no tiene sentido en tiempo de ejecución? Tendría que ver las clases separadas std::vector<int>y std::vector<float>. Y std::vector<int>::iteratory std::vector<float>::iterator, lo mismo paraconst_iteratory así. Y una vez que ingresa a la metaprogramación de plantillas, rápidamente termina creando instancias de cientos de plantillas, todas las cuales se vuelven a alinear y eliminar por el compilador. No tienen significado, excepto como parte de un metaprograma en tiempo de compilación. ¿Deberían todos estos cientos de clases ser visibles para la reflexión? Tendrían que hacerlo, porque de lo contrario nuestra reflexión sería inútil, si ni siquiera garantiza que las clases que definí realmente estarán allí . Y un problema secundario es que la clase de plantilla no existe hasta que se instancia. Imagina un programa que usa std::vector<int>. ¿Debería poder ver nuestro sistema de reflexión std::vector<int>::iterator? Por un lado, ciertamente lo esperarías. Es una clase importante, y se define en términos de std::vector<int>, lo que haceexisten en los metadatos. Por otro lado, si el programa nunca usa esta plantilla de clase de iterador, su tipo nunca se habrá instanciado, por lo que el compilador no habrá generado la clase en primer lugar. Y es demasiado tarde para crearlo en tiempo de ejecución, ya que requiere acceso al código fuente.

  • Y finalmente, la reflexión no es tan vital en C ++ como lo es en C #. La razón es nuevamente, la metaprogramación de plantilla. No puede resolver todo, pero en muchos casos en los que de otro modo recurriría a la reflexión, es posible escribir un metaprograma que haga lo mismo en tiempo de compilación. boost::type_traitsEs un ejemplo simple. ¿Quieres saber sobre el tipo T? Comprueba su type_traits. En C #, tendrías que pescar después de su tipo usando la reflexión. La reflexión aún sería útil para algunas cosas (el uso principal que puedo ver, que la metaprogramación no puede reemplazar fácilmente, es para el código de serialización autogenerado), pero conllevaría algunos costos significativos para C ++, y simplemente no es necesario tan a menudo como Está en otros idiomas.

Editar: en respuesta a los comentarios:

cdleary: Sí, los símbolos de depuración hacen algo similar, ya que almacenan metadatos sobre los tipos utilizados en el ejecutable. Pero también sufren los problemas que describí. Si alguna vez ha intentado depurar una versión de lanzamiento, sabrá a qué me refiero. Existen grandes lagunas lógicas en las que creó una clase en el código fuente, que se eliminó en el código final. Si usara la reflexión para algo útil, necesitaría que fuera más confiable y consistente. Tal como están las cosas, los tipos desaparecerían y desaparecerían casi cada vez que compila. Cambia un pequeño detalle, y el compilador decide cambiar qué tipos se insertan y cuáles no, como respuesta. ¿Cómo extraes algo útil de eso, cuando ' ¿Ni siquiera está garantizado que los tipos más relevantes estarán representados en sus metadatos? El tipo que estaba buscando puede haber estado allí en la última compilación, pero ahora se ha ido. Y mañana, alguien registrará un pequeño cambio inocente en una pequeña función inocente, lo que hace que el tipo sea lo suficientemente grande como para que no quede completamente en línea, por lo que volverá de nuevo. Eso sigue siendo útil para los símbolos de depuración, pero no mucho más que eso. Odiaría intentar generar código de serialización para una clase bajo esos términos. pero no mucho más que eso. Odiaría intentar generar código de serialización para una clase bajo esos términos. pero no mucho más que eso. Odiaría intentar generar código de serialización para una clase bajo esos términos.

Evan Teran: Por supuesto, estos problemas podrían resolverse. Pero eso se remonta a mi punto # 1. Tomaría mucho trabajo, y el comité de C ++ tiene muchas cosas que consideran más importantes. ¿El beneficio de obtener una reflexión limitada (y sería limitada) en C ++ es realmente lo suficientemente grande como para justificar centrarse en eso a expensas de otras características? ¿Existe realmente un gran beneficio al agregar características al lenguaje central que ya se puede hacer (principalmente) a través de bibliotecas y preprocesadores como QT? Quizás, pero la necesidad es mucho menos urgente que si tales bibliotecas no existieran. Sin embargo, para sus sugerencias específicas, creo que no permitirlo en las plantillas lo haría completamente inútil. No podría utilizar la reflexión en la biblioteca estándar, por ejemplo. ¿Qué tipo de reflexión nostd::vector? Las plantillas son una gran parte de C ++. Una característica que no funciona en las plantillas es básicamente inútil.

Pero tienes razón, se podría implementar alguna forma de reflexión. Pero sería un cambio importante en el idioma. Tal como está ahora, los tipos son exclusivamente una construcción en tiempo de compilación. Existen para el beneficio del compilador, y nada más. Una vez que el código ha sido compilado, no son ninguna clase. Si se estira, podría argumentar que las funciones aún existen, pero en realidad, todo lo que hay es un montón de instrucciones de ensamblador de salto, y una gran cantidad de push / pop de pila. No hay mucho para continuar cuando se agregan dichos metadatos.

Pero como dije, hay una propuesta de cambios en el modelo de compilación, agregando módulos autónomos, almacenando metadatos para tipos seleccionados, permitiendo que otros módulos los hagan referencia sin tener que meterse con #includes. Es un buen comienzo, y para ser honesto, me sorprende que el comité estándar no haya descartado la propuesta por ser un cambio demasiado grande. Entonces, ¿tal vez en 5-10 años? :)

jalf
fuente
2
¿La mayoría de estos problemas ya no tienen que resolverse con símbolos de depuración? No es que sea eficaz (debido a la alineación y la optimización que mencionó), pero podría permitir la posibilidad de reflexión haciendo lo que hagan los símbolos de depuración.
cdleary
2
Otra cosa sobre su primer punto: hasta donde yo sé, nadie ha intentado agregar reflejo a una implementación de C ++. No hay buena experiencia con eso. El Comité probablemente será reacio a tomar la iniciativa, particularmente después exporty vector<bool>.
David Thornley, el
18
Estoy de acuerdo en que C ++ no debería tener reflejo de tiempo de ejecución. Pero la reflexión en tiempo de compilación tiene algunos de los problemas anteriores, y podría usarse para que alguien cree una reflexión en tiempo de ejecución en clases particulares si así lo desea. ¿Puede acceder al tipo, nombre y características del enésimo método y el enésimo padre de una clase a través de una plantilla? ¿Y obtener el número de tales en tiempo de compilación? Haría factible la reflexión automática basada en CRTP, mientras que nadie paga por lo que no está usando.
Yakk - Adam Nevraumont
15
Su tercer punto es, en muchos aspectos, el más importante: C ++ está destinado a ser adecuado para escribir código independiente en plataformas donde la memoria cuesta dinero; si eliminar algún código no utilizado permitiría que un programa encajara en un microcontrolador que cuesta $ 2.00, en lugar de uno que cuesta $ 2.50, y si el código va en 1,000,000 de unidades, eliminar ese código puede ahorrar $ 500,000. Sin reflexión, el análisis estático a menudo puede identificar más del 90% del código inalcanzable; si Reflection está permitido, cualquier cosa a la que se pueda llegar a través de Reflection se debe considerar accesible, incluso si el 90% no lo está.
Supercat
2
definitivamente hay algo que el comité puede mejorar fácilmente, es decir finalmente negro sobre blanco que typeinfola name()función DEBE devolver el nombre que escribió el programador y no algo indefinido. Y denos también un stringifier para enumeradores. Esto es realmente crucial para la serialización / deserialización, ayudando a hacer fábricas, etc.
v.oddou
38

La reflexión requiere que algunos metadatos sobre los tipos se almacenen en algún lugar que se pueda consultar. Dado que C ++ se compila en el código de máquina nativo y sufre grandes cambios debido a la optimización, la vista de alto nivel de la aplicación se pierde en el proceso de compilación, por lo tanto, no será posible consultarlos en tiempo de ejecución. Java y .NET utilizan una representación de muy alto nivel en el código binario para máquinas virtuales que hacen posible este nivel de reflexión. Sin embargo, en algunas implementaciones de C ++, hay algo llamado Información de tipo de tiempo de ejecución (RTTI) que puede considerarse una versión simplificada de la reflexión.

Mehrdad Afshari
fuente
15
RTTI está en el estándar C ++.
Daniel Earwicker
1
Pero no todas las implementaciones de C ++ son estándar. He visto implementaciones que no admiten RTTI.
Mehrdad Afshari
3
Y la mayoría de las implementaciones que admiten RTTI también admiten desactivarlo a través de las opciones del compilador.
Michael Kohne el
21

Todos los idiomas no deben tratar de incorporar todas las características de todos los demás idiomas.

C ++ es esencialmente un ensamblador de macros muy, muy sofisticado. NO es (en un sentido tradicional) un lenguaje de alto nivel como C #, Java, Objective-C, Smalltalk, etc.

Es bueno tener diferentes herramientas para diferentes trabajos. Si solo tenemos martillos, todas las cosas se verán como clavos, etc. Tener lenguajes de script es útil para algunos trabajos, y los lenguajes OO reflexivos (Java, Obj-C, C #) son útiles para otra clase de trabajos, y super los lenguajes básicos eficientes y cercanos a la máquina son útiles para otra clase de trabajos (C ++, C, Assembler).

C ++ hace un trabajo increíble al extender la tecnología Assembler a niveles increíbles de gestión de complejidad y abstracciones para hacer que la programación de tareas más grandes y complejas sea mucho más posible para los seres humanos. Pero no es necesariamente un lenguaje que sea el más adecuado para aquellos que están abordando su problema desde una perspectiva estrictamente de alto nivel (Lisp, Smalltalk, Java, C #). Si necesita un idioma con esas características para implementar mejor una solución a sus problemas, ¡agradezca a aquellos que han creado dichos idiomas para que todos los usemos!

Pero C ++ es para aquellos que, por cualquier razón, necesitan tener una fuerte correlación entre su código y la operación de la máquina subyacente. Ya sea su eficiencia, o la programación de controladores de dispositivos, o la interacción con los servicios del sistema operativo de nivel inferior, o lo que sea, C ++ se adapta mejor a esas tareas.

C #, Java, Objective-C requieren un sistema de tiempo de ejecución mucho más grande y rico para admitir su ejecución. Ese tiempo de ejecución debe entregarse al sistema en cuestión, preinstalado para admitir el funcionamiento de su software. Y esa capa tiene que mantenerse para varios sistemas de destino, personalizada por ALGUNO OTRO IDIOMA para que funcione en esa plataforma. Y esa capa intermedia, esa capa adaptativa entre el sistema operativo host y su código, el tiempo de ejecución, casi siempre se escribe en un lenguaje como C o C ++, donde la eficiencia es el número 1, donde la comprensión predecible de la interacción exacta entre software y hardware puede ser buena. entendido y manipulado para obtener la máxima ganancia.

Me encanta Smalltalk, Objective-C y tener un sistema de tiempo de ejecución rico con reflexión, metadatos, recolección de basura, etc. ¡Se puede escribir un código increíble para aprovechar estas instalaciones! Pero eso es simplemente una capa más alta en la pila, una capa que debe descansar en las capas más bajas, que finalmente deben sentarse sobre el sistema operativo y el hardware. Y siempre necesitaremos un lenguaje que sea más adecuado para construir esa capa: C ++ / C / Assembler.

Anexo: C ++ 11/14 continúa expandiendo la capacidad de C ++ para admitir abstracciones y sistemas de nivel superior. El subprocesamiento, la sincronización, los modelos de memoria precisos, las definiciones de máquina abstracta más precisas están permitiendo a los desarrolladores de C ++ lograr muchas de las abstracciones de alto nivel que algunos de estos lenguajes de alto nivel solían tener dominio exclusivo, mientras continuaban proporcionando rendimiento del metal y excelente previsibilidad (es decir, subsistemas de tiempo de ejecución mínimos). Quizás los recursos de reflexión se habilitarán selectivamente en una futura revisión de C ++, para aquellos que lo deseen, o tal vez una biblioteca proporcionará dichos servicios de tiempo de ejecución (¿tal vez haya uno ahora, o el comienzo de uno en impulso?).

Mordachai
fuente
Su punto de vista sobre el tiempo de ejecución de un lenguaje que debe compilarse en otro idioma no es cierto en el caso de Objective-C, ya que su tiempo de ejecución está escrito en C (del cual Objective-C es un superconjunto).
Richard J. Ross III
Esa es una distinción sin diferencia. ¿Qué diferencia hace, cuando al final, el subsistema de tiempo de ejecución que utiliza Objective-C no está escrito en Objective-C, sino en C?
Mordachai
3
Lo siento; pero siempre que lo vincule correctamente, puede compilar un programa de Objective-C en C, de hecho lo hice aquí: stackoverflow.com/a/10290255/427309 . Toda su declaración anterior es falsa. El tiempo de ejecución es totalmente accesible a través de C, y es una de las cosas que lo convierte en un lenguaje dinámico tan poderoso.
Richard J. Ross III
1
El "tiempo de ejecución de C" es solo una biblioteca dinámica que contiene el código para la biblioteca estándar de C. Lo mismo para el "tiempo de ejecución C ++". Es bastante diferente de un sistema de tiempo de ejecución como el de Objective-C. Además ... aunque supongo que técnicamente podría usar el tiempo de ejecución Objective-C en C, todavía es solo un programa C que usa el tiempo de ejecución Objective-C: no puede compilar un programa Objective-C real en C.
celticminstrel
2
C ++ 11 con un modelo de memoria + atómica lo hace más parecido a un ensamblador portátil. Esas no son cosas de alto nivel, son cosas de bajo nivel para las que C ++ carecía anteriormente de soporte portátil. Pero la cantidad de UB en C ++ si hace algo mal lo hace muy diferente a los lenguajes basados ​​en VM como Java, y también a diferencia de cualquier lenguaje ensamblador específico. por ejemplo, el desbordamiento firmado es totalmente UB en la fuente C ++ y el compilador puede optimizar en función de ese hecho, incluso si compilamos, digamos x86, pero en asm en casi todas las plataformas simplemente se ajustará. Modern C ++ está muy lejos de ser un lenguaje ensamblador portátil.
Peter Cordes
11

Si realmente desea comprender las decisiones de diseño que rodean a C ++, busque una copia del Manual de referencia de C ++ anotado de Ellis y Stroustrup. NO está actualizado con el último estándar, pero pasa por el estándar original y explica cómo funcionan las cosas y, a menudo, cómo llegaron de esa manera.

Michael Kohne
fuente
66
También diseño y evolución de C ++ por Stroustrup
James Hopkin
9

La reflexión para los lenguajes que tiene es sobre la cantidad de código fuente que el compilador está dispuesto a dejar en su código objeto para permitir la reflexión, y cuánta maquinaria de análisis está disponible para interpretar esa información reflejada. A menos que el compilador guarde todo el código fuente, la reflexión estará limitada en su capacidad para analizar los datos disponibles sobre el código fuente.

El compilador de C ++ no guarda nada (bueno, ignorando RTTI), por lo que no obtienes reflejo en el lenguaje. (Los compiladores de Java y C # solo mantienen la clase, los nombres de los métodos y los tipos de retorno, por lo que obtienes un poco de datos de reflexión, pero no puedes inspeccionar las expresiones o la estructura del programa, y ​​eso significa incluso en esos lenguajes "habilitados para la reflexión") la información que puede obtener es bastante escasa y, en consecuencia, realmente no puede hacer mucho análisis).

Pero puede salir del lenguaje y obtener capacidades completas de reflexión. La respuesta a otra discusión de desbordamiento de pila sobre la reflexión en C discute esto.

Ira Baxter
fuente
7

La reflexión puede ser y ha sido implementada en c ++ antes.

No es una característica nativa de C ++ porque tiene un alto costo (memoria y velocidad) que el idioma no debe establecer de manera predeterminada: el idioma está orientado al "rendimiento máximo por defecto".

Como no debe pagar por lo que no necesita, y como usted mismo dice que se necesita más en los editores que en otras aplicaciones, debe implementarse solo donde lo necesite y no "forzar" a todo el código ( no necesita reflexionar sobre todos los datos con los que trabajará en un editor u otra aplicación similar).

Klaim
fuente
3
y no envía símbolos porque les permitiría a sus clientes / competidores ver su código ... esto a menudo se considera algo malo.
gbjbaanb
Tienes razón, aunque no lo hice sobre el problema de la exposición del código :)
Klaim
6

La razón por la que C ++ no tiene reflejo es que esto requeriría que los compiladores agreguen información de símbolos a los archivos de objetos, como qué miembros tiene un tipo de clase, información sobre los miembros, sobre las funciones y todo. Esencialmente, esto haría que los archivos de inclusión sean inútiles, ya que la información enviada por las declaraciones se leería de esos archivos de objeto (módulos). En C ++, una definición de tipo puede ocurrir varias veces en un programa al incluir los encabezados respectivos (siempre que todas esas definiciones sean iguales), por lo que habría que decidir dónde colocar la información sobre ese tipo, solo para nombrar uno. complicación aquí La optimización agresiva realizada por un compilador de C ++, que puede optimizar docenas de instancias de plantillas de clase, es otro punto fuerte. Es posible, pero como C ++ es compatible con C,

Johannes Schaub - litb
fuente
1
No entiendo cómo la optimización agresiva del compilador es un punto fuerte. ¿Puedes elaborar? Si el enlazador puede eliminar definiciones duplicadas de funciones en línea, ¿cuál es el problema con la información de reflexión duplicada? ¿No se agrega información de símbolos a los archivos de objetos de todos modos, para los depuradores?
Rob Kennedy el
1
El problema es que su información de reflexión puede ser inválida. Si el compilador elimina el 80% de las definiciones de clase, ¿qué van a decir sus metadatos de reflexión? En C # y Java, el lenguaje garantiza que si define una clase, permanece definida. C ++ permite que el compilador lo optimice.
jalf
1
@Rob, las optimizaciones son otro punto, no vinculado a la complicación de múltiples clases. Vea el comentario de @ jalf (y su respuesta) para lo que quise decir.
Johannes Schaub - litb
44
Si ejemplifico reflejar <T>, entonces no descarte ninguna información de T. Esto no parece un problema sin solución.
Joseph Garvin el
3

Hay toneladas de casos para usar la reflexión en C ++ que no pueden abordarse adecuadamente usando construcciones de tiempo de compilación como la metaprogramación de plantillas.

N3340 propone punteros ricos como una forma de introducir la reflexión en C ++. Entre otras cosas, aborda el problema de no pagar por una función a menos que la use.

apestar
fuente
2

Según Alistair Cockburn, el subtipo no puede garantizarse en un entorno reflexivo .

La reflexión es más relevante para los sistemas de tipeo latente. En C ++, sabes qué tipo tienes y sabes qué puedes hacer con él.

Nilone
fuente
En términos más generales, la capacidad de verificar la existencia de una característica que no existe sin introducir Comportamiento indefinido hace posible que agregar esa característica a una versión posterior de una clase cambie el comportamiento bien definido de los programas preexistentes, y por lo tanto, es imposible garantizar que agregar esa característica no "rompa" algo.
Supercat
2

La reflexión podría ser opcional, como una directiva de preprocesador. Algo como

#pragma enable reflection

De esa manera podemos tener lo mejor de ambos mundos, sin esta biblioteca pragma se crearía sin reflexión (sin ningún tipo de gastos generales como se discutió), luego dependería del desarrollador individual si desean velocidad o facilidad de uso.

usuario1401491
fuente
2

Si C ++ pudiera tener:

  • datos de miembros de clase para nombres de variables, tipos de variables y el const modificador
  • un iterador de argumentos de función (solo posición en lugar de nombre)
  • datos de miembros de clase para nombres de funciones, tipo de retorno y el const modificador
  • lista de clases primarias (en el mismo orden que se define)
  • datos para miembros de plantilla y clases para padres; la plantilla expandida (lo que significa que el tipo real estaría disponible para la API de reflexión y no la 'información de plantilla de cómo llegar allí')

Eso sería suficiente para crear bibliotecas muy fáciles de usar en el meollo del procesamiento de datos sin tipo que es tan frecuente en las aplicaciones web y de bases de datos actuales (todos los orms, mecanismos de mensajería, analizadores xml / json, serialización de datos, etc.).

Por ejemplo, la información básica respaldada por la Q_PROPERTYmacro (parte de Qt Framework) http://qt.nokia.com/doc/4.5/properties.html expandida para cubrir métodos de clase y e) - sería extraordinariamente beneficiosa para C ++ y para La comunidad de software en general.

Ciertamente, la reflexión a la que me refiero no cubriría el significado semántico o cuestiones más complejas (como los números de línea de código fuente de comentarios, análisis de flujo de datos, etc.), pero tampoco creo que sean necesarios para ser parte de un estándar de lenguaje.

Carreras de ligereza en órbita
fuente
@Vlad: Sí, si se agregan funciones que admiten la reflexión al idioma, se obtiene la reflexión en el idioma. Es probable que esto suceda solo si el comité de idiomas lo decreta, y creo que no lo hicieron a partir de 2011, y dudo que haya otro estándar de C ++ antes de 2020 AD. Entonces, buen pensamiento. Mientras tanto, si desea avanzar, es probable que tenga que salir de C ++.
Ira Baxter
0

Reflexión en C ++, creo que es de vital importancia si C ++ se va a utilizar como lenguaje para el acceso a la base de datos, el manejo de sesiones web / http y el desarrollo de GUI. La falta de reflexión evita ORM (como Hibernate o LINQ), analizadores XML y JSON que instancinan clases, serialización de datos y muchos otros signos (donde inicialmente se deben usar datos sin tipo para crear una instancia de una clase).

Se puede usar un cambio de tiempo de compilación disponible para un desarrollador de software durante el proceso de compilación para eliminar esta preocupación de 'usted paga por lo que usa'.

Si un desarrollador de firmware no necesita el reflejo para leer datos de un puerto serie, entonces no utilice el conmutador. Pero como desarrollador de bases de datos que quiere seguir usando C ++, estoy constantemente en fase con un código horrible y difícil de mantener que asigna datos entre miembros de datos y construcciones de bases de datos.

Ni la serialización de Boost ni ningún otro mecanismo están realmente resolviendo la reflexión, debe ser realizada por el compilador, y una vez que se haga, C ++ volverá a pensarse en las escuelas y se utilizará en el software que se ocupa del procesamiento de datos.

Para mí, este problema # 1 (y las primitivas de subprocesos ingenuos es el problema # 2).

vsp
fuente
44
¿Quién dijo que C ++ es para ser utilizado como un lenguaje de base de datos Access, sesión de Web hnadling o Dev GUI? Hay muchos idiomas mucho mejores para usar para ese tipo de cosas. Y un cambio de tiempo de compilación no resolverá el problema. Por lo general, la decisión de habilitar o deshabilitar la reflexión no será por archivo. Podría funcionar si se pudiera habilitar en tipos individuales. Si el programador puede especificar con un atributo o similar al definir un tipo, se deben generar metadatos de reflexión para él o no. ¿Pero un cambio global? Estaría paralizando el 90% del idioma solo para simplificar el 10%.
jalf
Entonces, si quiero un programa multiplataforma y tener acceso a una interfaz gráfica de usuario, ¿qué debo usar? ¿El columpio inflexible de Java? Las ventanas solo C #? Pero la verdad debe decirse, y la verdad es que hay muchos programas que se compilan en código ejecutable y ofrecen una interfaz gui y acceso a bases de datos, por lo que deben usar alguna base de datos y soporte de gui ... Y no son t utilizando QT. (debería haber sido nombrado MT (kit de herramientas de monstruos))
Coyote21
1
@ Coyote21: C # no ha sido solo de Windows durante años. (Aunque no soy fanático de Mono, funciona lo suficientemente bien para la mayoría de las cosas). Y Swing no es el único kit de herramientas GUI para Java. A decir verdad, cualquiera de los dos sería una mejor opción si quieres multiplataforma. C ++ siempre tendrá partes específicas de la plataforma aquí o allá si está haciendo algo no trivial.
cHao
No hay ninguna razón por la que necesite reflexión para ORM. Puede lograr todo eso con plantillas. Hay un montón de marcos que proporcionan ORM para C ++.
MrFox
0

Básicamente es porque es un "extra opcional". Muchas personas eligen C ++ sobre lenguajes como Java y C # para que tengan más control sobre la salida del compilador, por ejemplo, un programa más pequeño y / o más rápido.

Si elige agregar reflexión, hay varias soluciones disponibles .

Mella
fuente