Java tiene los medicamentos genéricos y de C++ proporciona una muy fuerte modelo de programación con templates.
Entonces, ¿cuál es la diferencia entre C++ y Java generics?

InformationsquelleAutor popopome | 2008-08-30

12 Comentarios

  1. 129

    Hay una gran diferencia entre ellos. En C++ no es necesario especificar una clase o una interfaz de tipo genérico. Es por eso que usted puede crear verdaderamente genérica de funciones y clases, con la salvedad de un acercamiento a escribir.

    template <typename T> T sum(T a, T b) { return a + b; }

    El método anterior añade dos objetos del mismo tipo, y puede ser utilizado para cualquier tipo de T que tiene el operador «+» disponible.

    En Java se puede especificar un tipo si desea llamar a métodos en los objetos del pasado, algo así como:

    <T extends Something> T sum(T a, T b) { return a.add ( b ); }

    En C++ las funciones genéricas/clases sólo puede ser definido en los encabezados, ya que el compilador genera diferentes funciones para diferentes tipos (que se invoca con). Para que la compilación es más lento. En Java la compilación no tienen una gran pena, pero Java utiliza una técnica llamada «el borrado», donde el tipo genérico se borra en tiempo de ejecución, por lo que en el tiempo de ejecución de Java es en realidad, se llama …

    Something sum(Something a, Something b) { return a.add ( b ); }

    Tan genéricos de programación en Java no es realmente útil, es sólo un poco de azúcar sintáctico para ayudar con la nueva construcción foreach.

    EDICIÓN: la opinión anterior sobre la utilidad fue escrito por un yo más joven. Java generics ayudar con seguridad de tipo de curso.

    • Sí, muy buena respuesta hasta que la última frase.
    • Es perfectamente correcto que es sólo una elaborada azúcar sintáctico.
    • No es puramente sintáctica de azúcar. El compilador utiliza esta información para la comprobación de tipos. Aunque la información no está disponible en tiempo de ejecución no digo algo el compilado utiliza simplemente «azúcar sintáctico». Si usted quiere llamar a eso, bueno, entonces C es simplemente azúcar sintáctico para la asamblea, y que acaba de azúcar sintáctico para el código de la máquina 🙂
    • Creo que azúcar sintáctico es útil.
    • Te perdiste un gran punto de diferencia, lo que usted puede utilizar para crear una instancia de un genérico. En c++ es posible utilizar la plantilla de <int N> y obtener un resultado diferente para cualquier número que se utiliza para crear instancias de ella. Se utiliza para el momento de la compilación meta progaming. Como la respuesta en: stackoverflow.com/questions/189172/c-templates-turing-complete
    • Hacer no que especifica un tipo’, en la forma de extends o super. Respuesta es incorrecta,
    • Tienes razón en decir que los medicamentos genéricos no necesitan especificar un sub o super clase. Pero en este ejemplo concreto donde se llama a un método en un objeto de este tipo genérico, el tipo genérico debe tener un super clase (o interfaz) que declara este método.
    • Y uno más para la corrección de su yo más joven!
    • la creación de subclases no sería necesario si el add interfaz se inyecta como un parámetro de la función también genéricamente parametrizadas en T.
    • Que es muy interesante! Se puede inventar un ejemplo para explicar esto?

  2. 119

    Java Genéricos son masivamente diferentes a las plantillas de C++.

    Básicamente en las plantillas de C++ son básicamente una glorificado preprocesador/macro set (Nota: ya que algunas personas parecen incapaces de comprender una analogía, no estoy diciendo que la plantilla de procesamiento de es una macro). En Java son básicamente azúcar sintáctico para minimizar repetitivo de fundición de Objetos. Aquí está una bastante decente introducción a las plantillas de C++ vs Java generics.

    A elaborar en este punto: cuando se utiliza una de plantillas de C++, básicamente lo que hace es crear otra copia del código, como si se utiliza un #define macro. Esto le permite hacer cosas como tener int parámetros en la plantilla de definiciones que determinan los tamaños de las matrices y tal.

    Java no funciona así. En Java todos los objetos medida de java.lang.Objeto así, pre-Genéricos, tendría que escribir un código como este:

    public class PhoneNumbers {
      private Map phoneNumbers = new HashMap();
    
      public String getPhoneNumber(String name) {
        return (String)phoneNumbers.get(name);
      }
    
      ...
    }

    porque todo el Java de la colección de tipos de Objeto utilizado como base el tipo de modo que usted puede poner cualquier cosa en ellos. Java 5 alrededor de los rollos, y añade que los genéricos, de modo que usted puede hacer cosas como:

    public class PhoneNumbers {
      private Map<String, String> phoneNumbers = new HashMap<String, String>();
    
      public String getPhoneNumber(String name) {
        return phoneNumbers.get(name);
      }
    
      ...
    }

    Y que todos Java Genéricos son: contenedores para convertir los objetos. Eso es debido a que Java Generics no refinado. Que tipo de uso de la supresión. Esta decisión fue tomada debido a que Java Generics llegó tan tarde en la pieza de la que no quieren romper la compatibilidad hacia atrás (un Map<String, String> es utilizable cuando un Map se llama). Compare esto con .Net/C# donde el tipo de borrado que no se usa, lo que conduce a diferencias de todo tipo (por ejemplo, puede utilizar los tipos primitivos y IEnumerable y IEnumerable<T> no guardan relación entre sí).

    Y una clase de uso de medicamentos genéricos compilado con Java 5+ compilador es utilizable en el JDK 1.4 (suponiendo que no utiliza ningún tipo de otras funciones o clases que requieren Java 5+).

    Por eso Java Generics se llaman azúcar sintáctico.

    Pero esta decisión sobre cómo hacer que los genéricos tiene profundos efectos tanto es así que la (magnífica) Java Generics FAQ ha surgido para responder a las muchas, muchas preguntas que las personas tienen acerca de Java Generics.

    Las plantillas de C++ tiene una serie de características que Java Genéricos no:

    • Uso de un tipo primitivo argumentos.

      Por ejemplo:

      template<class T, int i>
      class Matrix {
        int T[i][i];
        ...
      }

      Java no permite el uso de un tipo primitivo de los argumentos en los genéricos.

    • Uso de predeterminado argumentos de tipo, que es una función que me pierda en Java pero hay compatibilidad hacia atrás razones para esto;

    • Java permite la delimitación de los argumentos.

    Por ejemplo:

    public class ObservableList<T extends List> {
      ...
    }

    Lo que realmente no es necesario subrayar que la plantilla de invocaciones con diferentes argumentos realmente son de tipos diferentes. Que ni siquiera comparten los miembros estáticos. En Java esto no es el caso.

    Aparte de las diferencias con los medicamentos genéricos, la integridad, la de aquí es una comparación básicos de C++ y Java (y otro).

    Y también puedo sugerir Pensando en Java. Como un programador de C++ muchos de los conceptos como objetos a ser una segunda naturaleza, ya, pero hay sutiles diferencias, por lo que puede ser vale la pena tener un texto introductorio incluso si usted gana partes.

    Mucho de lo que vas a aprender cuando el aprendizaje de Java está en todas las bibliotecas (estándar–lo que viene en el JDK–y no estándar, que incluye comúnmente utilizados cosas como la Primavera). Java sintaxis es más detallado que la sintaxis de C++ y no tiene un montón de características de C++ (por ejemplo, sobrecarga de operadores, la herencia múltiple, el destructor mecanismo, etc), pero que no es estrictamente lo hacen un subconjunto de C++, ya sea.

    • Son completamente diferentes en la aplicación, pero equivalente ( o al menos similar ) en concepto, que es lo que tina le preguntó.
    • Que no son equivalentes en cuanto a concepto. El mejor ejemplo es la curiosa recurrente plantilla de patrón. La segunda mejor estar orientados a la política de diseño. El tercer mejor es el hecho de que C++ permite a los números enteros que se pasan en los soportes de ángulo (myArray<5>).
    • No, no son equivalentes en cuanto a concepto. Existe cierta coincidencia en el concepto, pero no mucho. Ambos permiten crear Lista de<T>, pero eso es como va. Las plantillas de C++ ir mucho más allá.
    • Importante tener en cuenta que el tipo de borrado problema significa más que simplemente compatibilidad con versiones anteriores para Map map = new HashMap<String, String>. Esto significa que usted puede implementar el nuevo código en un viejo JVM y se ejecutará, debido a las similitudes en el código de byte.
    • Las plantillas de C++ no tienen nada que ver con los preprocesadores o macros. Nunca se expanda a texto.
    • Tenga en cuenta que he dicho «básicamente una glorificado preprocesador/macro». Era una analogía, ya que cada declaración de la plantilla va a crear más líneas de código (en oposición a Java/C#).
    • Tal vez y tal vez no crear más código – los compiladores modernos son bastante buenos para eliminar código duplicado; pero el punto es que la creación de instancias de plantilla no se parece en nada el texto de la macro de expansión pensando en esos términos puede llevar a errores desagradables.
    • No estoy de acuerdo. Si usted odn no pensar en esos términos puede cometer el error de pensar instancia estática miembros son compartidos entre los tipos de plantilla, que no lo son. Código de la plantilla no está muy por encima de copiar-y-pegar (y no me refiero a esto de mala manera) por lo tanto la macro comparación.
    • Código de la plantilla es es diferente de copiar-y-pegar. Si usted piensa en términos de la expansión de macro, tarde o temprano tendrá que ser golpeado por los pequeños errores como este: womble.decadentplace.org.reino unido/c++/…
    • enlace roto.
    • IEnumerable<T> hereda de IEnumerable, así que no diría que no tienen ninguna relación entre sí.
    • Java Genéricos son no azúcar sintáctico, porque extienden el Java tipo de sistema. Es cierto que las limitaciones de la JVM les impiden ofrecer a la clase de eficiencia ventajas que otros idiomas obtener de polimorfismo paramétrico, pero que es una aplicación preocupación.
    • He utilizado varios compiladores de C++, donde las plantillas de hecho ampliar el texto.

  3. 78

    C++ dispone de plantillas. Java tiene que los medicamentos genéricos, los cuales se ven un poco parecida a las plantillas de C++, pero son muy, muy diferentes.

    Plantillas de trabajo, como el nombre implica, proporcionando el compilador con un (wait for it…) plantilla que se puede utilizar para generar el código seguro mediante la cumplimentación de los parámetros de la plantilla.

    Genéricos, como yo los entiendo, el trabajo de la otra manera: el tipo de los parámetros utilizados por el compilador para verificar que el código mediante el uso de ellos es de tipo seguro, pero el código resultante se genera sin tipos en todo.

    Pensar en las plantillas de C++ como un muy buena macro sistema, y Java generics como una herramienta para la generación automática de typecasts.

     

    • Esta es una muy buena, concisa explicación. Un tweak estaría tentado a hacer es que Java generics es una herramienta para la generación automática de typecasts que están garantizados para estar seguro (con algunas condiciones). En algunas maneras en las que está relacionado con C++’s const. Un objeto en C++ no será modificada a través de un const puntero a menos que el const-ness se arrojó lejos. Asimismo, las conversiones implícitas creado por tipos genéricos en Java están garantizados para estar «seguro» a menos que el tipo de los parámetros manualmente arrojó lejos en algún lugar en el código.
  4. 15

    Otra característica que las plantillas de C++ tienen que Java genéricos no es la especialización. Que le permite tener una implementación diferente para los tipos específicos. Así que usted puede, por ejemplo, tienen un gran versión optimizada para una int, sin dejar de tener una versión genérica para el resto de los tipos. O usted puede tener diferentes versiones de puntero y no los tipos de puntero. Esto es útil si usted desea operar en la eliminan las referencias de objeto cuando entregó un puntero.

    • +1 plantilla de especialización es muy importante en tiempo de compilación metaprogramación, esta diferencia en sí misma, que hace que java generics que mucho menos potente
  5. 13

    Hay una gran explicación de este tema en Java Genéricos y Colecciones
    Por Maurice Naftalin, Felipe Wadler. Yo recomiendo este libro. Citar:

    Genéricos en Java se asemejan a las plantillas en
    C++. … La sintaxis es deliberadamente
    similares y la semántica
    deliberadamente diferente. …
    Semánticamente, Java genéricos son
    definido por el borrado, donde como C++
    las plantillas se definen por la expansión.

    Por favor leer la explicación completa aquí.

    ¿Cuáles son las diferencias entre

    (fuente: oreilly.com)

  6. 5

    Básicamente, AFAIK, las plantillas de C++ crear una copia del código para cada tipo, mientras que Java generics utilizar exactamente el mismo código.

    Sí, puede decir que de plantillas de C++ es equivalente a la de Java genérico concepto ( aunque más bien habría que decir de Java genéricos son equivalentes a la de C++ en concepto )

    Si usted está familiarizado con C++del mecanismo de plantilla, se podría pensar que los medicamentos genéricos son similares, pero la similitud es superficial. Los medicamentos genéricos no generar una nueva clase para cada especialización, ni permiten la plantilla «metaprogramación.»

    de: Java Generics

  7. 3

    Java y C#) genéricos parecen ser un simple tiempo de ejecución tipo de mecanismo de sustitución.


    Las plantillas de C++ son una compilación en tiempo de construcción que le dan una forma de modificar el lenguaje para satisfacer sus necesidades. En realidad son puramente funcional de la lengua que el compilador ejecuta durante una compilación.

  8. 3

    Otra de las ventajas de las plantillas de C++ es la especialización.

    template <typename T> T sum(T a, T b) { return a + b; }
    template <typename T> T sum(T* a, T* b) { return (*a) + (*b); }
    Special sum(const Special& a, const Special& b) { return a.plus(b); }

    Ahora, si usted llama a la suma con los punteros, el segundo método será llamado, si usted llama a la suma con la no-puntero objetos el primer método que será llamado, y si se llama sum con Special objetos, la tercera se llama. No creo que esto es posible con Java.

    • Puede ser debido a que Java no tiene punteros..!! puede usted explicar con un ejemplo mejor?
  9. 2

    Voy a resumir en una sola frase: plantillas de crear nuevos tipos de medicamentos genéricos restringe los tipos existentes.

    • Su explicación es tan breve! Y hace perfectamente sentido para las personas que entienden el tema. Pero para la gente que no entiende todavía, no ayuda mucho. (Que es el caso de alguien pidiendo pregunta ENTONCES, ¿lo tienes?)
  10. 1

    @Keith:

    Que el código es realmente malo y aparte de los más pequeños fallos (template se omite, la especialización de la sintaxis se ve de forma diferente), parcial especialización no de trabajo en función de las plantillas, sólo en las plantillas de clase. El código, sin embargo, el trabajo sin parcial de la plantilla de especialización, en lugar de utilizar el viejo y simple sobrecarga:

    template <typename T> T sum(T a, T b) { return a + b; }
    template <typename T> T sum(T* a, T* b) { return (*a) + (*b); }
    • ¿Por qué es esto una respuesta y no un comentario?
    • por una vez, porque fue publicado mucho antes de que los comentarios se llevaron a cabo en el Desbordamiento de Pila. Por otro, porque no sólo es un comentario – es también una respuesta a la pregunta: algo así como el código anterior no es posible en Java.
  11. 1

    La respuesta de abajo es del libro el Agrietamiento de La Codificación de la Entrevista Soluciones para el Capítulo 13, que creo que es muy buena.

    La implementación de Java de genéricos está enraizada en la idea de»tipo de borrado:’Esta técnica elimina los tipos parametrizados cuando el código fuente se traduce a la Máquina Virtual de Java (JVM) bytecode. Por ejemplo, supongamos que usted tiene el código Java a continuación:

    Vector<String> vector = new Vector<String>();
    vector.add(new String("hello"));
    String str = vector.get(0);

    Durante la compilación, este código es re-escrito en:

    Vector vector = new Vector();
    vector.add(new String("hello"));
    String str = (String) vector.get(0);

    El uso de Java generics en realidad no cambia mucho acerca de nuestras capacidades; sólo hizo las cosas un poco más bonito. Por esta razón, Java genéricos son a veces llamados»azúcar sintáctico:’.

    Esto es muy diferente de C++. En C++, las plantillas son, esencialmente, una glorificado macro set, con el compilador de crear una nueva copia de la plantilla de código para cada tipo. Prueba de ello es el hecho de que una instancia de Miclase no compartir una variable estática withMyClass. Remolque instancias de Miclase, sin embargo, comparten una variable estática.

    /*** MyClass.h ***/
     template<class T> class MyClass {
     public:
     static int val;
     MyClass(int v) { val v;}
     };
     /*** MyClass.cpp ***/
     template<typename T>
     int MyClass<T>::bar;
    
     template class MyClass<Foo>;
     template class MyClass<Bar>;
    
     /*** main.cpp ***/
     MyClass<Foo> * fool
     MyClass<Foo> * foo2
     MyClass<Bar> * barl
     MyClass<Bar> * bar2
    
     new MyClass<Foo>(10);
     new MyClass<Foo>(15);
     new MyClass<Bar>(20);
     new MyClass<Bar>(35);
     int fl fool->val; //will equal 15
     int f2 foo2->val; //will equal 15
     int bl barl->val; //will equal 35
     int b2 bar2->val; //will equal 35

    En Java, las variables estáticas son compartidos a través de las instancias de Miclase, independientemente de los diferentes parámetros de tipo.

    Java generics y las plantillas de C ++ tienen un número de otras diferencias. Estos incluyen:

    • Las plantillas de C++ pueden utilizar los tipos primitivos como int. Java no puede ni debe
      en lugar de utilizar Entero.
    • En Java, puede restringir la plantilla del tipo de los parámetros de un
      cierto tipo. Por ejemplo, usted podría utilizar genéricos para implementar un
      CardDeck y especificar que el tipo de parámetro debe extenderse desde el
      CardGame.
    • En C++, el tipo de parámetro puede ser instanciado, mientras que Java no
      apoyo esto.
    • En Java, el tipo de parámetro (es decir, los Foo en Miclase) no puede ser
      utilizado para los métodos estáticos y variables, ya que estos serían compartidos entre MyClass y MyClass. En C++, estas clases son diferentes, por lo que el tipo de parámetro puede ser utilizado para los métodos estáticos y variables.
    • En Java, todas las instancias de Miclase, independientemente de su tipo de los parámetros, son del mismo tipo. El tipo de parámetros son borrados en tiempo de ejecución. En C++, las instancias con diferentes parámetros de tipo son de tipos diferentes.
  12. 0

    Plantillas no son sino un macro sistema. La sintaxis de azúcar. Se han expandido, antes de la compilación (o, al menos, los compiladores se comporta como si fuese el caso).

    Ejemplo:

    Supongamos que queremos dos funciones. Una función toma dos secuencias (lista, matrices, vectores, lo que va) de los números y devuelve su producto interior. Otra función toma una longitud, genera dos secuencias de longitud, pasa a la primera función y devuelve el resultado. El problema es que podríamos cometer un error en la segunda función, por lo que estas dos funciones no son realmente de la misma longitud. Necesitamos que el compilador nos advierten en este caso. No cuando el programa se está ejecutando, pero cuando se está compilando.

    En Java puede hacer algo como esto:

    import java.io.*;
    interface ScalarProduct<A> {
    public Integer scalarProduct(A second);
    }
    class Nil implements ScalarProduct<Nil>{
    Nil(){}
    public Integer scalarProduct(Nil second) {
    return 0;
    }
    }
    class Cons<A implements ScalarProduct<A>> implements ScalarProduct<Cons<A>>{
    public Integer value;
    public A tail;
    Cons(Integer _value, A _tail) {
    value = _value;
    tail = _tail;
    }
    public Integer scalarProduct(Cons<A> second){
    return value * second.value + tail.scalarProduct(second.tail);
    }
    }
    class _Test{
    public static Integer main(Integer n){
    return _main(n, 0, new Nil(), new Nil());
    }
    public static <A implements ScalarProduct<A>> 
    Integer _main(Integer n, Integer i, A first, A second){
    if (n == 0) {
    return first.scalarProduct(second);
    } else {
    return _main(n-1, i+1, 
    new Cons<A>(2*i+1,first), new Cons<A>(i*i, second));
    //the following line won't compile, it produces an error:
    //return _main(n-1, i+1, first, new Cons<A>(i*i, second));
    }
    }
    }
    public class Test{
    public static void main(String [] args){
    System.out.print("Enter a number: ");
    try {
    BufferedReader is = 
    new BufferedReader(new InputStreamReader(System.in));
    String line = is.readLine();
    Integer val = Integer.parseInt(line);
    System.out.println(_Test.main(val));
    } catch (NumberFormatException ex) {
    System.err.println("Not a valid number");
    } catch (IOException e) {
    System.err.println("Unexpected IO ERROR");
    }
    }
    }

    En C# se puede escribir casi la misma cosa. Pruebe a volver a escribir en C++, y no va a compilar, quejándose acerca de la infinita expansión de las plantillas.

    • Bueno, esto es 3 años, pero yo soy de responder de todos modos. No veo tu punto. La razón de Java genera un Error para que la Línea de comentarios es porque usted estaría llamando a una función que espera dos Una con diferentes Argumentos (Una y Contras<a>) y esto es muy básico, y también ocurre cuando no hay genéricos están involucrados. C++ que hace demasiado. Aparte de eso, este código me dio cáncer, ya que es realmente horrible. Sin embargo, usted todavía podría hacerlo igual que en C++, se tiene que para las modificaciones de curso, debido a que C++ no es Java, pero que no es un diaadvantage de C++Plantillas.
    • no, usted NO PUEDE hacer eso en C++. Ninguna cantidad de modificaciones permitiría eso. Y eso ES una desventaja de las plantillas de C++.
    • Lo que el Código debía hacer – advertir acerca de la longitud diferente – no hacer. En su comentario ejemplo sólo se produce de errores, debido a la no coincidencia de Argumentos. Que Trabaja en C++, también. Puede escribir Código que es semánticamente equivalente y la manera mejor de este lío en C++ y en Java.
    • Es lo que hace. Argumentos no coinciden exactamente debido a que las longitudes son diferentes. Usted no puede hacer eso en C++.

Dejar respuesta

Please enter your comment!
Please enter your name here