Há uma grande diferença entre eles. No C ++, você não precisa especificar uma classe ou uma interface para o tipo genérico. É por isso que você pode criar funções e classes verdadeiramente genéricas, com a ressalva de uma digitação mais flexível.
template<typename T> T sum(T a, T b){return a + b;}
O método acima adiciona dois objetos do mesmo tipo e pode ser usado para qualquer tipo T que tenha o operador "+" disponível.
Em Java, você deve especificar um tipo se quiser chamar métodos nos objetos passados, algo como:
<T extendsSomething> T sum(T a, T b){return a.add ( b );}
No C ++, funções / classes genéricas só podem ser definidas em cabeçalhos, pois o compilador gera funções diferentes para tipos diferentes (com os quais é chamado). Portanto, a compilação é mais lenta. Em Java, a compilação não possui uma penalidade maior, mas o Java usa uma técnica chamada "apagamento", onde o tipo genérico é apagado no tempo de execução, portanto, no tempo de execução, o Java está realmente chamando ...
Something sum(Something a,Something b){return a.add ( b );}
Portanto, a programação genérica em Java não é realmente útil, é apenas um pouco de açúcar sintático para ajudar na nova construção foreach.
EDIT: a opinião acima sobre utilidade foi escrita por um eu mais jovem. Os genéricos de Java ajudam na segurança de tipos, é claro.
Ele está perfeitamente correto de que é apenas um açúcar sintático elaborado.
alphazero
31
Não é açúcar puramente sintático. O compilador usa essas informações para verificar os tipos. Mesmo que as informações não estejam disponíveis no tempo de execução, eu não chamaria algo que os compilados usam simplesmente "açúcar sintático". Se você chamá-lo assim, bem, então C é apenas açúcar sintático para montagem, e isso é só açúcar sintático para código de máquina :)
DTECH
42
Eu acho que o açúcar sintático é útil.
poitroae
5
Você perdeu um grande ponto de diferença, o que pode ser usado para instanciar um genérico. Em c ++, é possível usar o modelo <int N> e obter um resultado diferente para qualquer número usado para instancia-lo. É usado para meta progame em tempo de compilação. Como a resposta em: stackoverflow.com/questions/189172/c-templates-turing-complete
stonemetal
2
Você não precisa 'especificar um tipo', na forma de um extendsou de super. A resposta está incorreta #
Marquis of Lorne
124
Os Java Generics são massivamente diferentes dos modelos C ++.
Basicamente, nos modelos C ++ há basicamente um conjunto glorificado de pré-processador / macro ( Nota: como algumas pessoas parecem incapazes de compreender uma analogia, não estou dizendo que o processamento de modelos é uma macro). Em Java, eles são basicamente açúcar sintático para minimizar a conversão de objetos em clichês. Aqui está uma introdução bastante decente aos modelos C ++ e aos genéricos Java .
Para elaborar esse ponto: quando você usa um modelo C ++, está basicamente criando outra cópia do código, como se tivesse usado uma #definemacro. Isso permite que você faça coisas como ter intparâmetros nas definições de modelo que determinam tamanhos de matrizes e outros.
Java não funciona assim. Em Java, todos os objetos se estendem a partir de java.lang.Object , portanto, pré-genéricos, você escreveria um código como este:
porque todos os tipos de coleção Java usavam Object como seu tipo base, para que você pudesse colocar qualquer coisa neles. O Java 5 rola e adiciona genéricos para que você possa fazer coisas como:
E isso é tudo o que os Java Generics são: invólucros para converter objetos. Isso ocorre porque o Java Generics não é refinado. Eles usam apagamento de tipo. Essa decisão foi tomada porque o Java Generics apareceu tão tarde na peça que eles não queriam quebrar a compatibilidade com versões anteriores (a Map<String, String>é utilizável sempre que Mapfor solicitado). Compare isso com .Net / C # onde o apagamento de tipo não é usado, o que leva a todos os tipos de diferenças (por exemplo, você pode usar tipos primitivos IEnumerablee IEnumerable<T>não ter relação um com o outro).
E uma classe usando genéricos compilados com um compilador Java 5+ é utilizável no JDK 1.4 (supondo que ele não use outros recursos ou classes que exijam o Java 5+).
É por isso que os Java Generics são chamados de açúcar sintático .
Mas essa decisão sobre como fazer genéricos tem efeitos profundos, tanto que as (excelentes) Perguntas frequentes sobre Java Generics surgiram para responder às muitas e muitas perguntas que as pessoas têm sobre Java Generics.
Os modelos C ++ têm vários recursos que o Java Generics não possui:
Java não permite o uso de argumentos de tipo primitivo em genéricos.
Uso de argumentos de tipo padrão , que é um recurso que sinto falta em Java, mas existem motivos de compatibilidade com versões anteriores;
Java permite delimitar argumentos.
Por exemplo:
publicclassObservableList<T extendsList>{...}
Realmente precisa ser enfatizado que as invocações de modelos com argumentos diferentes são realmente tipos diferentes. Eles nem compartilham membros estáticos. Em Java, esse não é o caso.
E também posso sugerir Pensando em Java . Como programador de C ++, muitos dos conceitos, como objetos, já serão de segunda natureza, mas existem diferenças sutis; portanto, pode valer a pena ter um texto introdutório, mesmo que você revele partes.
Muito do que você aprenderá ao aprender Java é todas as bibliotecas (tanto padrão - o que vem no JDK) quanto fora do padrão, que inclui coisas comumente usadas como Spring). A sintaxe Java é mais detalhada que a sintaxe C ++ e não possui muitos recursos C ++ (por exemplo, sobrecarga de operador, herança múltipla, mecanismo destruidor etc.), mas isso também não o torna estritamente um subconjunto de C ++.
Eles não são equivalentes em conceito. O melhor exemplo é o padrão curiosamente recorrente do modelo. O segundo melhor é o design orientado a políticas. O terceiro melhor é o fato de que o C ++ permite que números inteiros sejam passados entre colchetes angulares (myArray <5>).
Max Lybbert
1
Não, eles não são equivalentes em conceito. Há alguma sobreposição no conceito, mas não muito. Ambos permitem que você crie a Lista <T>, mas é o mais longe possível. Modelos C ++ vão muito mais longe.
jalf
5
É importante observar que o problema de apagamento de tipo significa mais do que apenas compatibilidade com versões anteriores Map map = new HashMap<String, String>. Isso significa que você pode implementar um novo código em uma JVM antiga e ela será executada devido às semelhanças no bytecode.
Yuval Adam
1
Você notará que eu disse "basicamente um pré-processador / macro glorificado". Foi uma analogia porque cada declaração de modelo criará mais código (em oposição a Java / C #).
Cletus
4
O código do modelo é muito diferente de copiar e colar. Se você pensar em termos de expansão de macro, mais cedo ou mais tarde você vai ser atingido por erros sutis como esta: womble.decadentplace.org.uk/c++/...
Nemanja Trifunovic
86
C ++ tem modelos. O Java possui genéricos, que se parecem com modelos C ++, mas são muito, muito diferentes.
Os modelos funcionam, como o nome indica, fornecendo ao compilador um modelo (aguarde ...) que ele pode usar para gerar código de tipo seguro preenchendo os parâmetros do modelo.
Os genéricos, como eu os entendo, funcionam de maneira inversa: os parâmetros de tipo são usados pelo compilador para verificar se o código que os utiliza é seguro, mas o código resultante é gerado sem tipos.
Pense nos modelos C ++ como um bom sistema macro e os Java genéricos como uma ferramenta para gerar automaticamente previsões de tipo.
Essa é uma explicação concisa muito boa. Um ajuste que eu ficaria tentado a fazer é que os genéricos Java são uma ferramenta para gerar automaticamente previsões tipográficas que são seguras (com algumas condições). De certa forma, eles estão relacionados aos C ++ const. Um objeto em C ++ não será modificado por meio de um constponteiro, a menos que const-ness seja eliminado. Da mesma forma, as conversões implícitas criadas por tipos genéricos em Java são garantidas como "seguras", a menos que os parâmetros de tipo sejam eliminados manualmente em algum lugar do código.
Laurence Gonsalves 01/03
16
Outro recurso que os modelos C ++ têm que os genéricos Java não têm é a especialização. Isso permite que você tenha uma implementação diferente para tipos específicos. Assim, você pode, por exemplo, ter uma versão altamente otimizada para um int , enquanto ainda possui uma versão genérica para o restante dos tipos. Ou você pode ter versões diferentes para tipos de ponteiro e não ponteiro. Isso é útil se você deseja operar no objeto não referenciado quando recebe um ponteiro.
+1 modelo de especialização é incrivelmente importante para metaprogramming em tempo de compilação - esta diferença em si torna os genéricos Java que muito menos potente
Faisal Vali
13
Há uma grande explicação para esse tópico em Java Generics and Collections
Por Maurice Naftalin, Philip Wadler. Eu recomendo este livro. Citar:
Os genéricos em Java se parecem com modelos em C ++. ... A sintaxe é deliberadamente semelhante e a semântica é deliberadamente diferente. ... Semanticamente, os genéricos Java são definidos por apagamento, enquanto os modelos C ++ são definidos por expansão.
Basicamente, os modelos AFAIK, C ++ criam uma cópia do código para cada tipo, enquanto os genéricos Java usam exatamente o mesmo código.
Sim, você pode dizer que o modelo C ++ é equivalente ao conceito genérico Java (embora seja mais apropriado dizer que os genéricos Java são equivalentes ao conceito C ++)
Se você conhece o mecanismo de modelo do C ++, pode pensar que os genéricos são semelhantes, mas a semelhança é superficial. Os genéricos não geram uma nova classe para cada especialização, nem permitem a "metaprogramação de modelos".
Os genéricos Java (e C #) parecem ser um mecanismo de substituição simples do tipo tempo de execução.
Os modelos C ++ são uma construção em tempo de compilação que permite modificar a linguagem para atender às suas necessidades. Na verdade, eles são uma linguagem puramente funcional que o compilador executa durante uma compilação.
Outra vantagem dos modelos C ++ é a especialização.
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(constSpecial& a,constSpecial& b){return a.plus(b);}
Agora, se você chamar soma com ponteiros, o segundo método será chamado; se você chamar soma com objetos que não são ponteiros, o primeiro método será chamado e, se você chamar sumcom Specialobjetos, o terceiro será chamado. Eu não acho que isso seja possível com Java.
Sua explicação é tão breve! E faz perfeitamente sentido para pessoas que entendem bem o tópico. Mas para pessoas que ainda não o entendem, isso não ajuda muito. (Que é o caso de alguém faz a pergunta no SO, entendeu?)
Jakub
1
@Keith:
Esse código está realmente errado e, além das pequenas falhas ( templateomitidas, a sintaxe da especialização parece diferente), a especialização parcial não funciona em modelos de função, apenas em modelos de classe. No entanto, o código funcionaria sem especialização parcial do modelo, usando sobrecarga antiga simples:
template<typename T> T sum(T a, T b){return a + b;}template<typename T> T sum(T* a, T* b){return(*a)+(*b);}
@ Laurence: pela primeira vez, porque foi publicado muito antes de os comentários serem implementados no Stack Overflow. Por outro, porque não é apenas um comentário - também é uma resposta para a pergunta: algo como o código acima não é possível em Java.
Konrad Rudolph
1
A resposta abaixo é do livro Cracking The Coding Interview Solutions para o Capítulo 13, que eu acho muito bom.
A implementação dos genéricos Java está enraizada na ideia de "apagamento de tipo: 'Essa técnica elimina os tipos parametrizados quando o código-fonte é convertido no bytecode da Java Virtual Machine (JVM). Por exemplo, suponha que você tenha o código Java abaixo:
O uso de genéricos Java não mudou muito sobre nossos recursos; apenas tornou as coisas um pouco mais bonitas. Por esse motivo, os genéricos Java às vezes são chamados de "açúcar sintático: '.
Isso é bem diferente do C ++. No C ++, os modelos são essencialmente um conjunto de macro glorificado, com o compilador criando uma nova cópia do código do modelo para cada tipo. Prova disso é que uma instância do MyClass não compartilha uma variável estática com o MyClass. No entanto, as instâncias de reboque do MyClass compartilharão uma variável estática.
/*** MyClass.h ***/template<class T>classMyClass{public:staticint val;MyClass(int v){ val v;}};/*** MyClass.cpp ***/template<typename T>intMyClass<T>::bar;templateclassMyClass<Foo>;templateclassMyClass<Bar>;/*** main.cpp ***/MyClass<Foo>* fool
MyClass<Foo>* foo2
MyClass<Bar>* barl
MyClass<Bar>* bar2
newMyClass<Foo>(10);newMyClass<Foo>(15);newMyClass<Bar>(20);newMyClass<Bar>(35);int fl fool->val;// will equal 15int f2 foo2->val;// will equal 15int bl barl->val;// will equal 35int b2 bar2->val;// will equal 35
Em Java, variáveis estáticas são compartilhadas entre instâncias do MyClass, independentemente dos diferentes parâmetros do tipo.
Os modelos genéricos Java e C ++ têm várias outras diferenças. Esses incluem:
Modelos C ++ podem usar tipos primitivos, como int. Java não pode e deve usar Integer.
Em Java, você pode restringir os parâmetros de tipo do modelo para serem de um determinado tipo. Por exemplo, você pode usar genéricos para implementar um CardDeck e especificar que o parâmetro type deve se estender do CardGame.
No C ++, o parâmetro type pode ser instanciado, enquanto o Java não suporta isso.
Em Java, o parâmetro type (ou seja, o Foo em MyClass) não pode ser usado para métodos e variáveis estáticos, pois eles seriam compartilhados entre MyClass e MyClass. No C ++, essas classes são diferentes, portanto o parâmetro type pode ser usado para métodos e variáveis estáticas.
Em Java, todas as instâncias do MyClass, independentemente de seus parâmetros de tipo, são do mesmo tipo. Os parâmetros de tipo são apagados no tempo de execução. No C ++, instâncias com diferentes parâmetros de tipo são diferentes.
Modelos não passam de um sistema macro. Sintaxe de açúcar. Eles são totalmente expandidos antes da compilação real (ou, pelo menos, os compiladores se comportam como se fosse o caso).
Exemplo:
Digamos que queremos duas funções. Uma função pega duas seqüências (lista, matrizes, vetores, o que for necessário) de números e retorna seu produto interno. Outra função leva um comprimento, gera duas seqüências desse comprimento, as passa para a primeira função e retorna seu resultado. O problema é que podemos cometer um erro na segunda função, para que essas duas funções não sejam do mesmo tamanho. Precisamos do compilador para nos avisar neste caso. Não quando o programa está sendo executado, mas quando está compilando.
Em Java, você pode fazer algo assim:
import java.io.*;interfaceScalarProduct<A>{publicInteger scalarProduct(A second);}classNilimplementsScalarProduct<Nil>{Nil(){}publicInteger scalarProduct(Nil second){return0;}}classCons<A implementsScalarProduct<A>>implementsScalarProduct<Cons<A>>{publicIntegervalue;public A tail;Cons(Integer _value, A _tail){value= _value;
tail = _tail;}publicInteger scalarProduct(Cons<A> second){returnvalue* second.value+ tail.scalarProduct(second.tail);}}class_Test{publicstaticInteger main(Integer n){return _main(n,0,newNil(),newNil());}publicstatic<A implementsScalarProduct<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,newCons<A>(2*i+1,first),newCons<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));}}}publicclassTest{publicstaticvoid main(String[] args){System.out.print("Enter a number: ");try{BufferedReaderis=newBufferedReader(newInputStreamReader(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");}}}
Em C #, você pode escrever quase a mesma coisa. Tente reescrevê-lo em C ++, e ele não será compilado, reclamando da expansão infinita de modelos.
Ok, isso tem 3 anos, mas estou respondendo de qualquer maneira. Eu não entendo o seu ponto. Todo o motivo pelo qual Java gera um erro para essa linha comentada é porque você chamaria uma função que espera dois A com argumentos diferentes (A e Contras <A>) e isso é realmente básico e também acontece quando nenhum genérico está envolvido. O C ++ também faz isso. Além disso, esse código me deu câncer porque é realmente horrível. No entanto, você ainda faria isso no C ++, pois é necessário fazer algumas modificações, porque o C ++ não é Java, mas isso não é uma desvantagem dos modelos do C ++.
Clock16 de
@clocktown não, você não pode fazer isso em C ++. Nenhuma quantidade de modificações permitiria isso. E isso é uma desvantagem dos modelos C ++.
MigMit
O que seu código deveria fazer - avisar sobre diferentes comprimentos - não funciona. No seu exemplo comentado, ele só produz erros devido a argumentos não correspondentes. Isso funciona em C ++ também. Você pode digitar código que seja semanticamente equivalente e muito melhor que essa bagunça em C ++ e em Java.
Clock6
Faz. Os argumentos não correspondem exatamente porque os comprimentos são diferentes. Você não pode fazer isso em C ++.
A principal diferença entre C ++ e Java reside na dependência da plataforma. Enquanto o C ++ é uma linguagem dependente da plataforma, Java é uma linguagem independente da plataforma.
A declaração acima é a razão pela qual o C ++ é capaz de fornecer tipos genéricos verdadeiros. Embora o Java tenha uma verificação rigorosa e, portanto, eles não permitem o uso de genéricos da maneira que o C ++ permite.
Respostas:
Há uma grande diferença entre eles. No C ++, você não precisa especificar uma classe ou uma interface para o tipo genérico. É por isso que você pode criar funções e classes verdadeiramente genéricas, com a ressalva de uma digitação mais flexível.
O método acima adiciona dois objetos do mesmo tipo e pode ser usado para qualquer tipo T que tenha o operador "+" disponível.
Em Java, você deve especificar um tipo se quiser chamar métodos nos objetos passados, algo como:
No C ++, funções / classes genéricas só podem ser definidas em cabeçalhos, pois o compilador gera funções diferentes para tipos diferentes (com os quais é chamado). Portanto, a compilação é mais lenta. Em Java, a compilação não possui uma penalidade maior, mas o Java usa uma técnica chamada "apagamento", onde o tipo genérico é apagado no tempo de execução, portanto, no tempo de execução, o Java está realmente chamando ...
Portanto, a programação genérica em Java não é realmente útil, é apenas um pouco de açúcar sintático para ajudar na nova construção foreach.
EDIT: a opinião acima sobre utilidade foi escrita por um eu mais jovem. Os genéricos de Java ajudam na segurança de tipos, é claro.
fonte
extends
ou desuper
. A resposta está incorreta #Os Java Generics são massivamente diferentes dos modelos C ++.
Basicamente, nos modelos C ++ há basicamente um conjunto glorificado de pré-processador / macro ( Nota: como algumas pessoas parecem incapazes de compreender uma analogia, não estou dizendo que o processamento de modelos é uma macro). Em Java, eles são basicamente açúcar sintático para minimizar a conversão de objetos em clichês. Aqui está uma introdução bastante decente aos modelos C ++ e aos genéricos Java .
Para elaborar esse ponto: quando você usa um modelo C ++, está basicamente criando outra cópia do código, como se tivesse usado uma
#define
macro. Isso permite que você faça coisas como terint
parâmetros nas definições de modelo que determinam tamanhos de matrizes e outros.Java não funciona assim. Em Java, todos os objetos se estendem a partir de java.lang.Object , portanto, pré-genéricos, você escreveria um código como este:
porque todos os tipos de coleção Java usavam Object como seu tipo base, para que você pudesse colocar qualquer coisa neles. O Java 5 rola e adiciona genéricos para que você possa fazer coisas como:
E isso é tudo o que os Java Generics são: invólucros para converter objetos. Isso ocorre porque o Java Generics não é refinado. Eles usam apagamento de tipo. Essa decisão foi tomada porque o Java Generics apareceu tão tarde na peça que eles não queriam quebrar a compatibilidade com versões anteriores (a
Map<String, String>
é utilizável sempre queMap
for solicitado). Compare isso com .Net / C # onde o apagamento de tipo não é usado, o que leva a todos os tipos de diferenças (por exemplo, você pode usar tipos primitivosIEnumerable
eIEnumerable<T>
não ter relação um com o outro).E uma classe usando genéricos compilados com um compilador Java 5+ é utilizável no JDK 1.4 (supondo que ele não use outros recursos ou classes que exijam o Java 5+).
É por isso que os Java Generics são chamados de açúcar sintático .
Mas essa decisão sobre como fazer genéricos tem efeitos profundos, tanto que as (excelentes) Perguntas frequentes sobre Java Generics surgiram para responder às muitas e muitas perguntas que as pessoas têm sobre Java Generics.
Os modelos C ++ têm vários recursos que o Java Generics não possui:
Uso de argumentos do tipo primitivo.
Por exemplo:
Java não permite o uso de argumentos de tipo primitivo em genéricos.
Uso de argumentos de tipo padrão , que é um recurso que sinto falta em Java, mas existem motivos de compatibilidade com versões anteriores;
Por exemplo:
Realmente precisa ser enfatizado que as invocações de modelos com argumentos diferentes são realmente tipos diferentes. Eles nem compartilham membros estáticos. Em Java, esse não é o caso.
Além das diferenças com os genéricos, para completar, aqui está uma comparação básica de C ++ e Java (e outra ).
E também posso sugerir Pensando em Java . Como programador de C ++, muitos dos conceitos, como objetos, já serão de segunda natureza, mas existem diferenças sutis; portanto, pode valer a pena ter um texto introdutório, mesmo que você revele partes.
Muito do que você aprenderá ao aprender Java é todas as bibliotecas (tanto padrão - o que vem no JDK) quanto fora do padrão, que inclui coisas comumente usadas como Spring). A sintaxe Java é mais detalhada que a sintaxe C ++ e não possui muitos recursos C ++ (por exemplo, sobrecarga de operador, herança múltipla, mecanismo destruidor etc.), mas isso também não o torna estritamente um subconjunto de C ++.
fonte
Map map = new HashMap<String, String>
. Isso significa que você pode implementar um novo código em uma JVM antiga e ela será executada devido às semelhanças no bytecode.C ++ tem modelos. O Java possui genéricos, que se parecem com modelos C ++, mas são muito, muito diferentes.
Os modelos funcionam, como o nome indica, fornecendo ao compilador um modelo (aguarde ...) que ele pode usar para gerar código de tipo seguro preenchendo os parâmetros do modelo.
Os genéricos, como eu os entendo, funcionam de maneira inversa: os parâmetros de tipo são usados pelo compilador para verificar se o código que os utiliza é seguro, mas o código resultante é gerado sem tipos.
Pense nos modelos C ++ como um bom sistema macro e os Java genéricos como uma ferramenta para gerar automaticamente previsões de tipo.
fonte
const
. Um objeto em C ++ não será modificado por meio de umconst
ponteiro, a menos queconst
-ness seja eliminado. Da mesma forma, as conversões implícitas criadas por tipos genéricos em Java são garantidas como "seguras", a menos que os parâmetros de tipo sejam eliminados manualmente em algum lugar do código.Outro recurso que os modelos C ++ têm que os genéricos Java não têm é a especialização. Isso permite que você tenha uma implementação diferente para tipos específicos. Assim, você pode, por exemplo, ter uma versão altamente otimizada para um int , enquanto ainda possui uma versão genérica para o restante dos tipos. Ou você pode ter versões diferentes para tipos de ponteiro e não ponteiro. Isso é útil se você deseja operar no objeto não referenciado quando recebe um ponteiro.
fonte
Há uma grande explicação para esse tópico em Java Generics and Collections Por Maurice Naftalin, Philip Wadler. Eu recomendo este livro. Citar:
Por favor, leia a explicação completa aqui .
(fonte: oreilly.com )
fonte
Basicamente, os modelos AFAIK, C ++ criam uma cópia do código para cada tipo, enquanto os genéricos Java usam exatamente o mesmo código.
Sim, você pode dizer que o modelo C ++ é equivalente ao conceito genérico Java (embora seja mais apropriado dizer que os genéricos Java são equivalentes ao conceito C ++)
de: Java Generics
fonte
Os genéricos Java (e C #) parecem ser um mecanismo de substituição simples do tipo tempo de execução.
Os modelos C ++ são uma construção em tempo de compilação que permite modificar a linguagem para atender às suas necessidades. Na verdade, eles são uma linguagem puramente funcional que o compilador executa durante uma compilação.
fonte
Outra vantagem dos modelos C ++ é a especialização.
Agora, se você chamar soma com ponteiros, o segundo método será chamado; se você chamar soma com objetos que não são ponteiros, o primeiro método será chamado e, se você chamar
sum
comSpecial
objetos, o terceiro será chamado. Eu não acho que isso seja possível com Java.fonte
Vou resumir em uma única frase: modelos criam novos tipos, genéricos restringe tipos existentes.
fonte
@Keith:
Esse código está realmente errado e, além das pequenas falhas (
template
omitidas, a sintaxe da especialização parece diferente), a especialização parcial não funciona em modelos de função, apenas em modelos de classe. No entanto, o código funcionaria sem especialização parcial do modelo, usando sobrecarga antiga simples:fonte
A resposta abaixo é do livro Cracking The Coding Interview Solutions para o Capítulo 13, que eu acho muito bom.
A implementação dos genéricos Java está enraizada na ideia de "apagamento de tipo: 'Essa técnica elimina os tipos parametrizados quando o código-fonte é convertido no bytecode da Java Virtual Machine (JVM). Por exemplo, suponha que você tenha o código Java abaixo:
Durante a compilação, esse código é reescrito em:
O uso de genéricos Java não mudou muito sobre nossos recursos; apenas tornou as coisas um pouco mais bonitas. Por esse motivo, os genéricos Java às vezes são chamados de "açúcar sintático: '.
Isso é bem diferente do C ++. No C ++, os modelos são essencialmente um conjunto de macro glorificado, com o compilador criando uma nova cópia do código do modelo para cada tipo. Prova disso é que uma instância do MyClass não compartilha uma variável estática com o MyClass. No entanto, as instâncias de reboque do MyClass compartilharão uma variável estática.
Em Java, variáveis estáticas são compartilhadas entre instâncias do MyClass, independentemente dos diferentes parâmetros do tipo.
Os modelos genéricos Java e C ++ têm várias outras diferenças. Esses incluem:
fonte
Modelos não passam de um sistema macro. Sintaxe de açúcar. Eles são totalmente expandidos antes da compilação real (ou, pelo menos, os compiladores se comportam como se fosse o caso).
Exemplo:
Digamos que queremos duas funções. Uma função pega duas seqüências (lista, matrizes, vetores, o que for necessário) de números e retorna seu produto interno. Outra função leva um comprimento, gera duas seqüências desse comprimento, as passa para a primeira função e retorna seu resultado. O problema é que podemos cometer um erro na segunda função, para que essas duas funções não sejam do mesmo tamanho. Precisamos do compilador para nos avisar neste caso. Não quando o programa está sendo executado, mas quando está compilando.
Em Java, você pode fazer algo assim:
Em C #, você pode escrever quase a mesma coisa. Tente reescrevê-lo em C ++, e ele não será compilado, reclamando da expansão infinita de modelos.
fonte
Gostaria de citar askanydiferença aqui:
A principal diferença entre C ++ e Java reside na dependência da plataforma. Enquanto o C ++ é uma linguagem dependente da plataforma, Java é uma linguagem independente da plataforma.
A declaração acima é a razão pela qual o C ++ é capaz de fornecer tipos genéricos verdadeiros. Embora o Java tenha uma verificação rigorosa e, portanto, eles não permitem o uso de genéricos da maneira que o C ++ permite.
fonte