Ya hay algunos puntos buenos en otras respuestas, pero me gustaría proporcionar una respuesta más completa, abordando sus preguntas y declaraciones individualmente.
Si Java no proporciona una función que tiene C ++, significa que la función no es buena, por lo que deberíamos evitar usarla.
Esto ha sido bastante bien respondido: Java no es "las partes buenas" de C ++, ni hay ninguna razón para pensarlo.
En particular, aunque los méritos de cada característica individual de C ++ son discutibles, muchas de las características de C ++ 11 / C ++ 14 que no son parte de Java no se excluyen necesariamente porque los diseñadores de Java pensaron que eran una mala idea. Como ejemplo, hasta la versión 8, Java no tenía lambdas, pero se introdujeron en C ++ en el estándar C ++ 11. Antes de Java 8, su suposición de que las características de C ++ que faltaban en Java faltaban por diseño porque "no son buenas" habría implicado que las lambdas como característica del lenguaje "no son buenas" (para horror de los LISPers de todas partes, aunque son probablemente lo suficientemente horrorizado como para escuchar que aparentemente realmente te gusta Java). Pero ahora los diseñadores de Java han puesto su Sello de aprobación (TM) en lambdas, por lo que ahora son una buena cosa.
Para profundizar un poco más, incluso en Java 8, las lambdas como cierres no son tan flexibles como las lambdas de C ++ 14, pero esto puede deberse a limitaciones de la arquitectura JVM en lugar de una decisión consciente de que el enfoque más flexible es malo de un perspectiva del diseño del lenguaje.
El código C ++ con características específicas de C ++ (p. Ej .: funciones de amigo, herencia múltiple) solo puede ser mantenido o revisado por programadores de C ++, pero si solo escribimos C ++ como Java (sin la característica específica del lenguaje C ++), el código puede ser mantenido o revisado por ambos Programadores en C ++ y Java.
Esto es lo principal a lo que quería responder.
En términos generales, puede ser útil obtener revisiones de código de programadores que no están íntimamente familiarizados con el lenguaje que está utilizando. Pueden darle comentarios valiosos sobre la claridad de los nombres y comentarios de su función / método, y (como su pregunta lo indica correctamente) si el idioma es similar a uno o más idiomas que ya conocen, pueden seguir el flujo básico del programa y potencialmente atrapar errores lógicos.
Sin embargo, es no el caso de que este tipo de revisión volverá a ser "tan buena como" o "equivalente a" revisión de los desarrolladores que realmente conocen el idioma que está utilizando. Esencialmente, esto se debe a que hacer que un idioma se vea como otro normalmente ocultará diferencias sutiles, mientras que hacer que un idioma se comporte como otro (especialmente en el caso de C ++ y Java) puede no ser idiomático para el lenguaje y / o aún puede ser demasiado confuso para los revisores
Primero, pensemos en lo que significaría hacer que C ++ "se parezca" a Java. Como un caso simple, puede usar new
para instanciar objetos, al igual que en Java:
Foo foo = new Foo();
Pero los objetos instanciados de esta manera se usan en ->
lugar de .
llamar a métodos, por lo que si desea que las llamadas a métodos se parezcan a Java, debe escribir:
Foo& foo = *new Foo();
Pero esto no es idiomático; en particular, la memoria debe limpiarse más tarde utilizando delete &foo
, lo que algunos desarrolladores experimentados de C ++ podrían no darse cuenta de que es un código legal . De cualquier manera, no son divertidos símbolos que no son Java como asperjadas en todas partes, por lo que no puede absolutamente hacer que el lenguaje "se parece a" Java. (Podrías eliminar el *new
uso #define New *new
, o peor, #define new *new
pero simplemente estás rogando a tus compañeros desarrolladores que te odien). Y, como se mencionó anteriormente, delete
no existe en Java, por lo que en cualquier caso (como se menciona en otra respuesta ) realmente no puede hacer que el uso de objetos "se vea" como lo hace en Java sin pérdidas de memoria.
Pero el C ++ moderno incluye punteros inteligentes compartidos, que se comportan de manera muy similar a las referencias variables administradas en memoria de Java. Entonces, en cualquier lugar de Java que puedas escribir Foo foo = new Foo();
, podrías escribir:
std::shared_ptr<Foo> foo = std::make_shared<Foo>();
Ahora está utilizando una función de lenguaje que en realidad se parece mucho a la de Java. Pero de repente tienes mucho que explicar a los revisores que no son C ++: ¿qué es esto shared_ptr
? ¿De qué son las sutiles "trampas" difíciles make_shared
? (Utiliza el reenvío perfecto, que tiene algunos casos de falla y puede conducir a que se llame al constructor "incorrecto"). ¿Por qué es necesario invocar los métodos ->
, pero .
el compilador permite el uso con algunos métodos? ( shared_ptr
tiene sus propios métodos). Si el método Foo::reset(void)
existe, un desarrollador incauto podría intentar llamarlo foo.reset()
, lo que (si solo hay un puntero compartido que apunta a esa instancia de Foo
cuándo ocurre la llamada) eliminará la memoria subyacente y anulará foo
, y No es probable que los desarrolladores de Java capten este problema.
Por otra parte, C ++ tiene una gran cantidad de trampas que son específicos a la lengua. Lo mejor que puedo decir es que la mayoría de los desarrolladores de C ++ aprenden a lidiar con estas trampas desarrollando gradualmente su propio idioma para las prácticas "seguras" de C ++, que a menudo es algo único para ellos o para su equipo de desarrollo (ver, por ejemplo, la respuesta existente que menciona el Prácticas de codificación de Google y el comentario que dice que "los veteranos experimentados de C ++ generalmente rechazan las pautas de codificación de Google"). Parece que todas las afirmaciones de que el lenguaje puede ser demasiado complicado (en mi experiencia, al menos), generalmente se encuentran con alguna variación de "bueno, deja de usarlo mal". Me doy cuenta de que esta es una visión muy negativa de la comunidad C ++, y ciertamente hay desarrolladores experimentados más dispuestos a ayudar a los estudiantes de idiomas, pero sí parece ser una cierta actitud defensiva sobre, por ejemplo, un comportamiento indefinido (ver, por ejemplo, gran parte de la discusión en mi enlace de "trampas" más arriba).
Los desarrolladores de Java simplemente no serán útiles para encontrar y corregir estas dificultades a través de la revisión de código.
Es posible que algún día se le solicite convertir el código a Java.
Es completamente válido, incluso recomendable, tratar de tener en cuenta lo que podría sucederle a su código en el futuro mientras se encuentra en la fase de diseño.
Pero, en primer lugar, esta consideración particular parece una posibilidad remota: el código generalmente se reutiliza tal como está (por ejemplo, podría conectar parte o la totalidad del código C ++ en funcionamiento en algún software Java futuro utilizando una interfaz JNI) o reescribirlo completamente. que directamente "transcrito" manualmente.
Y, segundo, luego dices:
Cada característica específica del lenguaje C ++ (por ejemplo: herencia múltiple) debe tener alternativas para implementarse en Java ...
Esto esencialmente cancela su punto de "convertir a Java". Si el software se escribe en C ++ idiomático y luego se convierte a Java idiomático, no hay razón para esperar que esta conversión se haga (¡o podría!) Mediante la aplicación de un mapeo preciso uno a uno de las características de C ++ a las características de Java.
El código sin características específicas de C ++ suele ser más fácil de mantener.
No está claro lo que quiere decir aquí, pero en realidad estoy de acuerdo con algo de esto: a menos que tenga mucho cuidado, e incluso cuando tenga cuidado, las características de C ++ pueden provocar problemas de mantenimiento. El C ++ FQA Lite (un sitio web crítico con el lenguaje y sus seguidores de alguien que al menos parece entenderlo bastante bien) afirma que
... 80% de los desarrolladores entienden como máximo el 20% del lenguaje. No es el mismo 20% para diferentes personas, así que no cuentes con ellos para entender el código del otro.
TENGA EN CUENTA: si es un fanático de C ++ y llega a este punto en mi respuesta y se siente inclinado a saltar a los comentarios para argumentar que el autor de la FQA en realidad no entiende C ++ o es falso en la mayoría de sus argumentos , tenga en cuenta que (1) exactamente dos oraciones después de que lo cite, reconozco que la FQA es una fuente muy sesgada, y (2) realmente no importa por lo que estoy tratando de decir si el autor de la FQA entiende o no C ++ , y no estoy tratando de criticar C ++, y deberías leer el resto de la publicación sin asumir que soy anti-C ++ solo porque he citado el FQA. Fin de la nota
Del mismo modo, Linus Torvalds odia C ++ esencialmente por esta razón (advertencia: el enlace implica muchas palabrotas, en el verdadero estilo infame de Linus).
Obviamente, estos son enfoques muy sesgados al respecto, pero incluso los defensores de C ++ a menudo dicen que no debe usar la totalidad del conjunto de características del lenguaje (una vez más, consulte las pautas de codificación de Google; también, Bjarne Stroustrup, el creador de C ++ , ha declarado públicamente: "Dentro de C ++, hay un lenguaje mucho más pequeño y más limpio que lucha por salir").
Por lo tanto, creo que la idea de que las características de C ++ pueden ser demasiado fáciles de usar es un mérito, especialmente si proviene de un entorno Java. Además, la idea de aliviar estos problemas tiene mérito al restringirse a un subconjunto del lenguaje.
Sin embargo, decidir qué subconjunto usar basado en un lenguaje diferente no parece ser el enfoque correcto, a menos que el "lenguaje diferente" sea C, ya que realmente hay un subconjunto tipo C del lenguaje C ++. (Linus se refiere a esto en su discurso anterior, y Scott Meyers incluso se refiere a este subconjunto como un "sublenguaje"). El paradigma de tiempo de ejecución de Java (recolección de basura, ejecución en una VM) es tan fundamentalmente diferente de C ++ que es no está claro que haya lecciones útiles para extraer sobre el uso de C ++, y como se señaló anteriormente, tratar de extraer lecciones sobre C ++ directamente desde Java puede conducir a un código muy poco idiomático.
En su lugar, intente definir su "subconjunto aceptable" del idioma en una comprensión de cómo el idioma puede usarse idiomáticamente. Si desea un subconjunto bastante restrictivo que aún aproveche muchas de las características de C ++ más allá de lo que ofrece C, la guía de codificación de Google mencionada anteriormente podría ser un buen lugar para comenzar. Claro, obtendrás desarrolladores que dicen que "no hay un argumento racional" para algunas de las restricciones de Google , pero a menos que estés buscando contratar a Alexandrescu lejos de su trabajo en el lenguaje D (que en sí mismo debería decirte algo), eso es Probablemente está bien. Ciertamente es mejor que tratar de convertir C ++ en Java.
Otro buen punto de partida para un conjunto de directrices de código son las nuevas Directrices básicas de C ++ , un trabajo en progreso de Bjarne Stroustrup y Herb Sutter.
La única otra forma de lidiar con las deficiencias de C ++ es elegir un lenguaje diferente. Parece que le gusta Java, y cree que existe la posibilidad de que este proyecto se convierta en Java eventualmente. Como se señaló en otra respuesta, podrías ... comenzar con Java.
Hay dos razones por las que realmente podría necesitar usar algo que no sea Java:
- Realmente necesitas el rendimiento en tiempo de ejecución. En este caso, tratar C ++ como si fuera Java probablemente no lo ayudará, porque las técnicas similares a Java, como los punteros compartidos, degradan el rendimiento del tiempo de ejecución.
- Necesita el software para trabajar en una plataforma oscura que aún no es compatible con la JVM. En este caso, probablemente esté atrapado con lenguajes que tengan interfaces GCC o Clang. C y C ++ son candidatos obvios, pero también podría considerar algo como Rust. (Enchufe rápido: no he usado Rust ampliamente, pero se ve increíble y estoy ansioso por trabajar en un proyecto importante de Rust tan pronto como pueda, y creo que todos los que consideren comenzar un proyecto C ++ deberían considerar Rust como una alternativa).
Cada característica específica del lenguaje C ++ (por ejemplo, herencia múltiple) debe tener alternativas para implementarse en Java. Si no es así, eso significa que el patrón de diseño o la arquitectura del código es problemático.
Ya he abordado esto de alguna manera, pero intencionalmente omití tu segunda oración.
No estoy convencido de que algo así constexpr
, que no tendría ningún sentido en un lenguaje parcialmente JIT como Java, sea una indicación de una arquitectura no válida. Estoy más abierto a la idea de que el uso excesivo de la metaprogramación de plantillas podría ser más problemático de lo que vale, especialmente ahora que constexpr
existe para hacer una evaluación de la función en tiempo de compilación, pero está claro por el caso de constexpr
que no hay fallas de diseño si usted lo estás usando: simplemente te estás asegurando de que algunos cálculos se realicen incluso antes de ejecutar el código, lo que es un increíble aumento del rendimiento (consulta, por ejemplo, esta entrada para el problema de n-cuerpos de The Benchmark Game , que supera a todas las demás entradas excepto a otra) escrito en C ++,