Supongamos que estoy limitado a usar C ++ por el entorno en el proyecto. ¿Es bueno evitar el uso de algunas características del lenguaje que tiene C ++ pero que Java no tiene (por ejemplo: herencia múltiple, sobrecarga del operador)?
Creo que las razones son:
- Como Java es más nuevo que C ++, si Java no proporciona una característica que tiene C ++, significa que la característica no es buena, por lo que debemos evitar usarla.
- 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.
- Es posible que algún día se le solicite convertir el código a Java
- El código sin características específicas de C ++ suele ser más fácil de mantener
- 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.
¿Es eso cierto?
java
c++
code-quality
ggrr
fuente
fuente
volatile
, Java , acceso de miembro de clase de paquete privado, reflexión / introspección, finalmente bloques, excepciones verificadas, etc.? Toda la pregunta no tiene mucho sentido ... C ++ y Java son superficialmente similares, pero en última instancia lenguajes muy diferentes.SomeObject a = previousObject;
hace cosas muy diferentes en Java y C ++. En Java copia una referencia, mientras que en C ++ copia el objeto. En Java, las modificaciones aa
también afectarían al objeto anterior. En C ++, tiene dos objetos separados.Respuestas:
No. Esto es lamentablemente y terriblemente equivocado.
fuente
operator<<( ostream &, T const & )
generalmente se implementa a través defriend
. Ese es el problema con las declaraciones generales sobre lo que es una buena característica del lenguaje y lo que es malo: son buenos consejos, excepto cuando no lo son ...El hecho de que la sintaxis parezca similar en la superficie no significa que los dos idiomas sean compatibles.
1, 4 y 5 son realmente la misma pregunta:
Ahora, no soy fanático de C ++, pero decir "El código sin características específicas de C ++ es generalmente más fácil de mantener" es simplemente ridículo: ¿realmente crees que Java hizo todo bien y tomó todas las características buenas mientras ignoraba todas las malas? ¿Realmente crees que hay algo que es universalmente una característica "mala" o "buena"? Si es así, ¿por qué no tenemos un idioma que sea puramente bueno? Y no, Java ciertamente no es ese lenguaje. ¿Eso significa que Java y C ++ son inútiles? Por supuesto no.
¿Qué sucede si sus líderes deciden que va a migrar a C #, en lugar de Java? C # no solo admite operadores primarios, sino que también es el valor predeterminado: si va a requerir que la gente use, por ejemplo, en
obj.Equals(obj2)
lugar de hacerloobj == obj2
, la gente cometerá errores todo el tiempo. Incluso si se mantiene solo con las características comunes de los dos idiomas, hay diferentes expectativas , una cultura diferente. Si haces algo comoif (myField == null)
en C ++, la gente verá que eres un novato de inmediato. Si usaif (null == myField)
C #, la gente verá que todavía no es nativo de C #, las razones por las que los desarrolladores de C aprendieron a usar la variante "volteada" ya no existen en C #.Usando su lógica, deberíamos habernos quedado con el código de máquina o ensamblaje o COBOL, porque ¿por qué cambiar a algo como Pascal, cuando solo agrega nuevas características que sus programadores tendrán que aprender? ¿Por qué usaríamos algo como SQL, cuando ni siquiera tiene bucles ? ¿Por qué usaríamos algo más que SQL, cuando SQL no tiene bucles y X sí?
Código C ++ desde luego no puede ser mantenida por los programadores de Java. No puedo entender de dónde sacaste esta idea: ¿qué queda exactamente cuando limitas C ++ a solo las características que funcionan exactamente igual que en Java? Ni siquiera va a recibir llamadas a métodos, ni siquiera llamadas a funciones . Nuevamente, el hecho de que ambos idiomas utilicen llaves no significa que los idiomas sean intercambiables.
La conversión de código C ++ similar a Java va a ser extremadamente propenso a errores sin importar lo que haga. Hay demasiadas diferencias. Si le importa tener que volver a escribir su aplicación en un idioma diferente, piense en formas razonables de modularizar todo, de modo que pueda reemplazar las partes sin romper el todo. Pero al final, YAGNI: no importa lo que hagas, habrá un costo significativo para que tu código esté "listo para convertir a Java". Es muy probable que ese tiempo se aproveche mejor para agregar o mejorar sus funciones.
Usamos diferentes idiomas porque nos dan un conjunto diferente de herramientas para resolver problemas. Si necesita ejecutables que funcionan "en todas partes", vaya con Java. Si desea un código que compila "en todas partes", C ++ funciona bien. Si desea un código que sea fácil de entender y analizar, vaya con LISP o lo que sea. Pero puedo decirte una cosa: escribir código en un idioma como si lo estuvieras escribiendo en otro siempre es un error y sufrirás. Sin mencionar que cuando realmente contratas a un chico de C ++, ejecutará el segundo en que vea ese código "compatible con Java-ish". Y ... el chico Java hará lo mismo. Ya sabes, incluso "conociendo" tanto C ++ como Java, correría como el infierno :)
De hecho, tuve que trabajar en el código C (simple) escrito por un desarrollador de Pascal que parecía pensar como tú. Solía
#define
redefinir C para que se viera y se sintiera más como Pascal, con cosas como "COMENZAR se traduce en {". El resultado fue bastante predecible: un código que ni los desarrolladores de C ni Pascal pueden entender, y lleno de errores que fueron el resultado de la "abstracción" de Pascal sobre C. y Pascal y C son casi idénticos desde el punto de vista actual. Incluso ir a C <-> C ++ es mucho más que una diferencia, y eso sigue siendo algo así como algo así como C ++ <-> Java.fuente
myFunc()
versus(myFunc)
), y eso tiene una muy buena razón. Los lenguajes basados en LISP siguen siendo muy populares, especialmente entre las personas de matemáticas / física. Lo principal es realmente que los lenguajes LISPy son muy desconocidos para los programadores modernos de estilo C, pero esa no es razón para ignorarlo. Scheme, Clojure y, en cierta medida, los lenguajes basados en ML (OCaml, F # ...) son muy LISPy.if (myField == null)
comoif (myField = null)
, que compilará bien C / C ++, pero probablemente no hace lo que pretende. Por otro lado,if (null = myField)
arrojará un error, ya que no puede asignar a una constante.Contestaré sus preguntas en orden.
Sí, cualquier característica no presente en Java es anatema en el disco duro. Debe quemarse desde su base de código. Aquellos que no obedezcan serán abrumados, sus almas usadas para aplacar a los dioses RAID.
En caso de duda, escriba el código para el miembro menos competente de su equipo. El código se lee con mucha más frecuencia de lo que se escribe, y el código que es tan inteligente como puedes escribir es demasiado inteligente para leerlo. Las revisiones de código que el personal de recepción no entenderá deben ser rechazadas. Para ayudar, enséñeles cómo programar en Visual Basic 2.0 durante el fin de semana, luego emule su estilo de codificación en cualquier idioma que esté usando.
¡Cierto! Pero, ¿por qué detenerse en Java? Se le puede pedir que convierta el código a básico, ensamblador y / o perl algún día. Como hay intérpretes de perl en todos los idiomas, simplemente escriba su programa como una larga cadena de perl y marque argumentos en el idioma de su elección.
Ahora, cuando necesite cambiar de idioma, simplemente vuelva a escribir el código que envuelve la cadena perl.
Es cierto que el código que usa menos funciones es más fácil de mantener. Y como todos los idiomas son equivalentes a una máquina de Turing, y una máquina de Turing tiene la menor cantidad de características de cualquier lenguaje de programación, haga que el intérprete perl anterior ejecute una máquina de Turing (cinta y todo) que resuelva su problema.
Las características específicas del lenguaje C ++ en realidad tienen un uso valioso. Como no son Java, son anatema, y quienes lo usan pueden ser calificados como herejes. Si C ++ no tuviera esas características del lenguaje, no podría encontrar las que necesita sacrificar. ¡Las características del lenguaje C ++ resuelven problemas!
Mire, C ++ y Java tienen un conjunto diferente de capacidades. La programación en la intersección de C ++ y Java da como resultado un código que ha descartado la mayoría de las ventajas de ambos lenguajes.
Java se desarrolló parcialmente como reacción a algún abuso de las características de C ++. Esto no significa que la reacción haya sido justificada, especialmente años después, cuando las características han madurado.
Puede hacer cosas horribles con la sobrecarga del operador; pero ningún idioma puede evitar que se escriba un código horrible en el idioma, a menos que impida que todo el código se escriba en el idioma.
Y también puede hacer cosas muy elegantes con la sobrecarga del operador. Cosas simples, como un número complejo o una clase de matriz que funciona como un número complejo o una matriz.
Se debe tener precaución al usar las características de C ++ que no están disponibles en Java. El hecho de que su conjunto actual de desarrolladores en su nivel de habilidad actual no entienda una característica no significa que nunca deba usarse; al mismo tiempo, solo porque puede usar una función, no significa que deba hacerlo. Sin embargo, en una tienda pesada de Java, las probabilidades son que la resistencia sea más fuerte de lo que debería ser contra las características que no son de Java-esque.
La conversión de código entre idiomas se realiza mejor con una reescritura, sin importar cuán estructuralmente similares sean. Cualquier intento de hacerlo sin tal reescritura va a fallar miserablemente.
Muchas características específicas de C ++ son maravillas para el mantenimiento. El borrado de tipo (me gusta
std::function
) le permite desacoplar jerarquías, lo que reduce las dependencias. Los punteros inteligentes y los tiempos de vida deterministas y la RAII reducen las sorpresas de tiempo de ejecución y eliminan los recursos de recursos. Las pesadas verificaciones de tipo estático significan que el código no se compila, en lugar de no funcionar. Las mezclas reducen la duplicación de código. ADL permite la extensión ad-hoc independiente de interfaces entre jerarquías de tipos. Lambda le permite escribir código al lado de donde se usa. El reenvío y el movimiento reducen las copias y hacen que la programación de estilo funcional (sin efectos secundarios) sea eficiente. La sobrecarga del operador reduce el ruido de la línea y hace que el código se parezca más a las matemáticas que está modelando.Cuidado con el pozo de alquitrán de Turing. Puede implementar todo en cualquier idioma (incluida una máquina de Turing sin procesar con cinta), pero eso no significa que deba hacerlo . Emular características de C ++ usando construcciones tipo Java en C ++ es una idea horrible; resultará en un código imposible de mantener que nadie puede leer ni comprender.
Puede inspirarse en los diseños de Java y transferirlos a C ++. Soy un gran fanático de tomar las características del lenguaje Python e implementarlas en C ++, porque me gusta la sintaxis. Pero eso no significa que escriba mis métodos de clase como métodos estáticos tomando un self explícito, luego escriba un contenedor que reenvíe la llamada al método no estático.
El C ++ moderno no es muy parecido al lenguaje Java emulado y rechazado. No se bloquee por las características de un idioma; no hay "un lenguaje verdadero". Aprenda sobre nuevos idiomas y sus características, y absorba su carácter distintivo.
fuente
Solo voy a responder tus razones:
fuente
delete
.delete
. Por lo que recuerdo, en al menos uno de esos casos,new
tampoco fue necesaria la asignación dinámica ( ).make_shared
.Java tiene características que C ++ no tiene, como un recolector de basura incorporado, rápido y confiable, una jerarquía de objetos de raíz única y una potente introspección.
Las otras funciones de Java están diseñadas para funcionar junto con las funciones exclusivas de Java, y muchas de las omisiones de Java de las funciones de C ++ son posibles porque las nuevas funciones compensan la falta. Por ejemplo, Java no tiene objetos asignados a la pila con destructores deterministas, pero finalmente tiene bloques (y prueba con recursos desde Java 7) y el recolector de basura para compensar esta falta.
C ++ finalmente no tiene bloques o recolección de basura. Si no usa destructores porque no existen en Java (no cuento los finalizadores), está en el nivel C de gestión de recursos (es decir, todo manual), excepto que ni siquiera puede agrupar su limpieza en un bloque de limpieza al que vas, porque Java tampoco tiene goto. ¿Realmente crees que eso mejora la mantenibilidad?
Java tiene una jerarquía de objetos global donde cada clase deriva en última instancia de Objeto, y los pocos tipos primitivos también se pueden encuadrar automáticamente en tales clases. Esto permite escribir contenedores de objetos una vez, para mantener punteros a Object. Java 5 introdujo genéricos, que eliminan los moldes que tales contenedores necesitan, pero aún así se compilan prácticamente en el mismo código.
C ++ no tiene tal jerarquía. Para facilitar la escritura de contenedores que funcionan para varios tipos, utiliza plantillas, que son planos que el compilador crea instancias según sea necesario para diferentes tipos. ¿Prohibirá el uso de plantillas (y macros) e irá a la ruta C de escribir el mismo código de contenedor una y otra vez para diferentes tipos o usar punteros vacíos? (¡Espera, Java no tiene punteros vacíos!) ¿Estás seguro de que esto aumentaría la capacidad de mantenimiento?
Un lenguaje decente tiene una multitud de características que están diseñadas para funcionar juntas. Al prohibir características del lenguaje A porque el lenguaje B no las tiene, está paralizando el lenguaje A, porque no está al mismo tiempo agregando características de B que hacen que B sea un todo coherente.
Eso no quiere decir que no debe restringir las características permitidas de C ++. C ++ es un lenguaje grande e históricamente desarrollado que hace hincapié en permitir que el programador haga lo que quiere por seguridad y facilidad de uso, y no todas sus características en toda su flexibilidad son necesarias para construir buenos programas. Existen muchos estándares de codificación que restringen el uso de algunas funciones; por ejemplo, las pautas de Google prohíben principalmente la herencia múltiple, plantillas complejas y excepciones (aunque esta última es por razones históricas). Pero ninguna característica está prohibida "porque Java no la tiene"; las características se consideran solo en el marco de C ++.
fuente
Object
es más o menosvoid*
para la mayoría de los usos. Aún así, qué asco.finally
No es un reemplazo para ellos. Los dos idiomas son fundamentalmente diferentes.He debatido si molestarme en publicar otra respuesta cuando ya tiene un número que llega a conclusiones que parecen ser completamente razonables: que su idea es básicamente un desastre esperando a suceder. Sin embargo, creo que no han señalado algunas razones muy relevantes detrás de esa conclusión.
Las diferencias entre Java y C ++ son mucho más profundas que los detalles en los que parece haberse centrado.
Por ejemplo, habla de prohibir la herencia múltiple en C ++. Primero, señalaré que esto simplemente está perdiendo el punto. Java define "interfaces" como elementos separados de las "clases". Una clase solo hereda de otra clase, pero puede implementar un número arbitrario de interfaces.
C ++ no separa los dos conceptos de esa manera. Lo más cercano que C ++ analógico proporciona para implementar una interfaz en Java es heredar de otra clase. Como tal, para mantener los dos alineados razonablemente bien, es probable que necesite usar herencia múltiple en C ++, pero desea restringir algunas de esas clases base de la misma manera en que Java restringe una interfaz en comparación con una clase (es decir, esencialmente que especifica firmas de funciones pero, al menos en su mayoría, no implementaciones).
Sin embargo, eso apenas rasca la superficie de las diferencias reales entre los dos. En realidad, donde es probable que el código Java defina interfaces y las clases que implementan esas interfaces, es mucho más probable que el código C ++ defina algunas plantillas que funcionarán con cualquier clase que cumpla con sus requisitos (no solo aquellas definidas específicamente para implementar la interfaz (s) especifica).
Si honestamente quiere un código que sea básicamente "Java usando la sintaxis de C ++", seguramente tendrá que prohibir cualquier cosa y todo lo similar a este último. Deberá restringir el uso de plantillas a aproximadamente el nivel de "contenedor de T" que admiten los genéricos de Java. Desafortunadamente, hacer eso dará como resultado un código C ++ que es un desastre que nadie puede mantenerlo como existe ahora, sin mencionar la posibilidad a largo plazo de traducirlo a otro lenguaje de programación.
Si realmente desea código que se pueda convertir a otro idioma en el futuro, trate de hacerlo lo más limpio y legible posible. Lo ideal es escribir pseudocódigo y aun así ejecutarlo. Los enfoques de C ++ modernos bien escritos que son ideales mucho más de cerca que el subconjunto que ha sugerido. No importa cómo lo escriba, si alguna vez traduce a Java, tendrá que traducir el código, no solo la sintaxis de las declaraciones individuales.
fuente
Si va a escribir código en el lenguaje X, pase el tiempo para aprender el idioma correctamente y use todas las funciones que ofrece para ayudarlo a resolver el problema. Las cosas malas suceden cuando intenta hacer una traducción "palabra por palabra" de un idioma a otro, ya sea japonés a inglés o Java a C ++. Es mucho mejor comenzar con una buena comprensión del problema y expresar la solución de la manera más natural para el lenguaje que se utiliza.
Hace años vi un programa en C que no tenía sangría y cada declaración comenzó en la columna 7, porque el autor del código era un programador de Fortran que estaba usando C. Otros programadores de Fortran estaban nerviosos por estas cosas novedosas llamadas punteros. No tuve el valor de mencionar punteros a punteros, creo que se habrían desmayado en el acto.
Imagine contratar a alguien para mantener este código en el futuro. Si es un buen código de C ++, podrá contratar a un desarrollador de C ++ competente y ellos deberán poder orientarse. Si se trata de "Java en C ++", entonces ni los desarrolladores de C ++ ni Java tendrán un tiempo fácil para entender el código.
fuente
Todos sus motivos pueden ser refutados:
No significa que la característica no sea buena (ninguna característica puede ser inherentemente mala). Solo significa que la característica fue mal utilizada con frecuencia (o imposible de implementar debido a conceptos fundamentales, como punteros directos vs recolección de basura). Java, por definición, tiene como objetivo ser más fácil y más amigable para los programadores, de ahí la eliminación de características que demostraron ser fácilmente abusables.
Oh puede ser? Veamos el código C ++ más simple:
Vaya, no se utilizan funciones "específicas del idioma", ¡pero los desarrolladores de Java ya no las pueden mantener! Porque en Java se desreferencia con "." mientras que aquí es "->.
O C #. O Haskell. O Python O a Ruby. O COBOL (¡sí, puedes!). ¿Cómo puedes decir el futuro?
Exactamente opuesto. Cada característica se introdujo para facilitar la programación y, por lo tanto, hacerla más fácil de mantener. Por ejemplo: tome un programa que opera en flotadores. Ahora actualícelo para manejar números complejos. Operador sobrecargando al rescate!
¡Pero Java TIENE herencia múltiple! Se llama "interfaz". La implementación de Java es una solución alternativa problemática para evitar el temido diamante causado por tener todo derivado
Object
. Se hace introduciendointerface
cuál es el único propósito de ser algo de lo que no se derivaObject
. C ++ nunca tuvo este problema: no hay una base común obligatoria, por lo que cada clase puede funcionar como una interfaz sin el temido diamante.Nota al margen: Java introdujo recientemente ... métodos concretos en las interfaces. Se agregó una característica que C ++ siempre tuvo que resolver un problema que nunca estuvo allí.
También ha mencionado muy pocas "cosas que tiene C ++ pero Java no". Una de las mayores diferencias entre C ++ y Java es el control sobre el diseño de la memoria. Puede crear una matriz de punteros a los objetos (al igual que en Java) O puede crear un bloque de memoria contigua. Ahora, si tuviera que preocuparme por una característica de C ++ que pueda confundir a los desarrolladores de Java, algo tan oculto y sutil como este clasificaría en mi lista mucho más que lo obvio y reconocible a primera vista, como la herencia múltiple o los operadores sobrecargados.
En pocas palabras: el código limpio es código limpio. Java o C ++: la misma diferencia. Solo mantenlo simple. Las complicaciones innecesarias son la causa principal del mal código.
fuente
No, generalmente no debe escribir C ++ como si fuera Java, y definitivamente no debe omitir las características del lenguaje C ++ que no están presentes en Java.
Por un lado, Java es basura recolectada y, por lo tanto, no tiene equivalente a la palabra clave "eliminar" de C ++. Bien, entonces implementas un programa sin eliminar, porque según tus reglas, no está permitido.
Felicidades, ahora tienes una pérdida de memoria;). Eso tampoco es teórico: he visto esta situación exacta en un juego de código abierto.
Del mismo modo, Java no tiene nada parecido a los punteros de C ++, lo que descarta muchas convenciones de llamadas a funciones comunes.
Hay características de C ++ que quizás deberías evitar (ver más abajo), pero "no estar en Java" no es una buena prueba de fuego.
Las mejores pautas serían las siguientes:
El ítem (3) significa que no debe tener código de programadores Java en C ++ sin entrenarlos en C ++. Hay algunas diferencias sutiles pero muy importantes que podrían no aprender si intentan tratarlo como un extraño dialecto de Java.
El ítem (2) significa que, si su equipo específicamente se siente incómodo con la herencia múltiple (por ejemplo), y si hay una solución adecuada que no la usa, entonces puede ser mejor usar esa solución alternativa. Sin embargo, esto depende de su equipo específicamente. Por otro lado, si su equipo se siente más incómodo con esa solución alternativa que con la herencia múltiple, ¡use la herencia múltiple!
Por último, hay características de lenguaje de C ++ que, posiblemente, uno debería evitar. Si desea saber cuáles son, pregunte a los programadores de C ++ , en lugar de los programadores de un lenguaje diferente. Algunos ejemplos para comenzar son aritmética de puntero (sin consenso universal) y goto.
fuente
Ya hay algunos puntos buenos en otras respuestas, pero me gustaría proporcionar una respuesta más completa, abordando sus preguntas y declaraciones individualmente.
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.
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: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: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: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ícilesmake_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étodoFoo::reset(void)
existe, un desarrollador incauto podría intentar llamarlofoo.reset()
, lo que (si solo hay un puntero compartido que apunta a esa instancia deFoo
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 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:
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.
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
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:
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 queconstexpr
existe para hacer una evaluación de la función en tiempo de compilación, pero está claro por el caso deconstexpr
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 ++,fuente
import SomeVeryBasicPackage
y solo hiciste esto ?" Haga una pregunta avanzada y la primera respuesta es casi inevitablemente como "¿Por qué no lo hicisteimport SomeMagicalPackage
y solo hiciste eso ?"No.
Si "por el entorno del proyecto" está limitado a usar C ++, entonces hay poco, si es que tiene alguno, que pensar incluso en cualquier otra tecnología, sin importar cuánto prefiera personalmente / espere usar / evangelizarla.
Si "Technology X" o "Y" son compatibles con cualquier característica dada, no debería tener ninguna influencia en la forma en que construye su aplicación C ++.
Es una aplicación C ++, presumiblemente por alguna "Buena Razón" (ahora o en el pasado), por lo que debe escribirla como una aplicación C ++, utilizando lo que esa "caja de herramientas" en particular proporcione.
Si hay un requisito para portar la aplicación a alguna otra tecnología, entonces (y solo entonces) puede considerar características en otras plataformas. No tiene ningún sentido "cortar la nariz a pesar de su cara" en la remota posibilidad de que algo podría suceder. Sin embargo, recuerde que la reescritura generalizada es una operación costosa y arriesgada que es poco probable que la Administración asuma sin una muy buena razón para hacerlo.
Hubo un debate similar ("usar o no usar") algunos años atrás en el mundo de Visual Basic [.Net], donde alguien tuvo la brillante idea de que debería escribir aplicaciones de Visual Basic sin usar ninguno de los [lenguaje principal] funcionalidad proporcionada por el espacio de nombres Microsoft.VisualBasic. Sería como tratar de escribir una aplicación C ++ sin el espacio de nombres std ::; OK, es posible, pero ¿por qué alguien en su sano juicio se molestaría en hacerlo?
fuente
Microsoft.VisualBasic
espacio de nombres es un poco exagerado. Han pasado muchos años desde la última vez que lo usé, pero al menos al principio tenía como objetivo principal la compatibilidad con VB6 (y / o hacer que los programadores de VB6 se sientan "en casa"); en su mayoría proporcionaba funcionalidad que ya estaba disponible en el resto del marco en una forma más moderna (y mejor integrada), por lo que en proyectos nuevos rara vez tenía sentido usarla. Por el contrario, elstd::
espacio de nombres es donde reside toda la biblioteca estándar; evitarlo sería como evitar todo el BCL en .NET.Todas las respuestas actuales dicen que esto es algo malo, ya que debe aprovechar el lenguaje que está utilizando y también explicar por qué una característica de C ++ no es "mala" simplemente porque no está en jave. Contestaré esto desde un ángulo diferente.
Una cosa es evitar las características complejas de C ++, como la herencia múltiple, la sobrecarga del operador y la definición de su propia plantilla.
Pero cualquier problema que haga más que la tarea más simple:
No hay un subconjunto común de Java y C ++ que permita lo anterior, por lo tanto, lo que está preguntando es imposible de hacer. (Si estuviera preguntando sobre Java y C #, tendría muchas más posibilidades, ya que ambos usan recolectores de basura).
Sin embargo, podría requerir que el código se escriba para que un desarrollador de Java pueda entender lo que hace (pero no el "cómo" detallado) y esto sería sensato.
También puede diseñar su propio lenguaje que implementó en C ++ y JAVA .....
fuente
Nadie debería escribir ningún código que otros codificadores no entiendan. Si cree que el bloqueo de idioma es un problema, espere hasta que tenga el bloqueo de desarrollador. Es más probable que uno lo tenga como rehén que el otro.
Realmente no hay razones técnicas. Lo que ha creado es un escenario en el que se utilizó un lenguaje por cualquier razón, pero muchos desarrolladores actuales y posiblemente futuros no lo entienden realmente.
Supongo que es probable que los desarrolladores de Java escriban C ++ de la forma en que escriben en Java, entonces, ¿por qué hacerlo una regla? Puede descubrir algunas características específicas de C ++ que son más fáciles de implementar y mantener con un poco de instrucción / documentación de C ++ para sus desarrolladores de Java que la gran bola de desorden de Java con el que de otro modo estarían atrapados.
Este ha sido un argumento sobre los problemas de los programadores de BASIC que se mueven a lenguajes orientados a objetos. No es que implementen las prácticas de OOP en detrimento de los nuevos desarrolladores que no lo entienden, sino que no lo implementan en absoluto. Si lo hacen, generalmente se equivocan. Si algo se hace mal, debe eliminarse independientemente de la razón.
Además de alguien que simplemente copia y pega ciegamente el código, lo hará en muchas áreas que de todos modos no comprende.
fuente