Java vs C/C++

32 respostas
G

Então gente, mais uma vez vem a grande guerra!!

Faço parte de um grupo de pesquisa e aqui temos programadores (ou aspirantes a programadores) de Java, C e C++ e hoje surgiu uma discução sobre as duas linguagens óbvio que todos sabemos que não existe melhor linguagem e sim a que mais se aplica a determinada aplicação a ser desenvolvida, mas seguindo uma linha de vantagens e desvantagens, podemos inferir que o CG e a Portabilidade do Java são pontos bons e a JVM um ponto fraco?

Vlw gurizada!

32 Respostas

J

CG é o quê? Computação gráfica?

Para escrever software portável não necessáriamente se precisa de máquina virtual, mas em contrapartida a máquina virtual contribui com recursos que pode ou não tornar um projeto mais produtivo.

V

Primeiro de tudo. C e C++ são duas linguagens distintas.
Você quer saber em relação ao C ou ao C++?

J

ViniGodoy:
Primeiro de tudo. C e C++ são duas linguagens distintas.
Você quer saber em relação ao C ou ao C++?

aliás, eu também não entendi direito a questão

E

guisantogui:
Então gente, mais uma vez vem a grande guerra!!

Faço parte de um grupo de pesquisa e aqui temos programadores (ou aspirantes a programadores) de Java, C e C++ e hoje surgiu uma discução sobre as duas linguagens óbvio que todos sabemos que não existe melhor linguagem e sim a que mais se aplica a determinada aplicação a ser desenvolvida, mas seguindo uma linha de vantagens e desvantagens, podemos inferir que o CG e a Portabilidade do Java são pontos bons e a JVM um ponto fraco?

Vlw gurizada!

Desculpe - é GC (Garbage Collection), CL (Coleta de Lixo) ou CG (Honda?)

V

Eu citaria as seguintes (comparação de Java com C++):

Java:
VANTAGENS

  • Mais fácil de programar: managed code realmente é uma mão na roda;
  • Melhores relatórios de erros: stacktraces completos;
  • Melhores IDEs, depuradores e profilers;
  • Possibilidade de fazer reflexão;
  • Multiplataforma - o que facilita também montar o ambiente para programar em java (em C, é comum alguém ter compilado algo para plataforma X e você ter que baixar a API, entender o make e compilar o projeto para sua plataforma Y).
  • Mais fácil de se obter uma aplicação otimizada (o algoritmo de alocação de memória do GC é excelente, e a VM pode otimizar aplicações multi-thread com facilidade);

DESVANTAGENS:

  • Código fácil de descompilar;
  • Pouca integração com o sistema operacional (é o preço que se paga por ter uma VM);
  • Execução não determinística, o que inviabiliza real-time (preço que se paga por um garbage collector);
  • Baixo controle sobre o consumo de memória;
  • Sem suporte em diversos dispositivos e SOs;

C++
VANTAGENS

  • Portabilidade: Suporta um número MUITO maior de plataformas;
  • Suporta programação genérica;
  • Muito integrável com o sistema operacional e hardwares externos (ao custo de portabilidade);
  • Possibilidade de escrever uma aplicação com execução determinística e extremamente enxuta (você pode até mesmo escrever seu próprio algorítmo personalizado de alocação e desalocação de memória, pode saber o custo computacional exato de cada comando que utilizar, etc). Isso o torna ótimo candidato para o mercado de firmwares;
  • Mais otimizável. Embora o Java saia mais rápido “por default”, você pode chegar a um código no C++ mais rápido que qualquer equivalente em Java, desde que esteja disposto a pagar por isso;

DESVANTAGENS

  • Mais difícil de se programar;
  • Mais difícil achar programadores experientes na linguagem;
  • Erros difíceis de diagnosticar (especialmente os envolvendo templates);

Note que as vantagens que ressaltei acabam posicionando o C++ no local onde ele atua hoje: Em aplicações de tempo real, firmwares e aplicativos que usam recursos específicos dos sistemas operacionais (como a maior parte das aplicações desktop para usuários finais e games).

V

Vale ressaltar que algumas coisas são diferenças simplesmente. E podem ser usadas para o bem ou para o mal.
O C++ permite compilação condicional, por exemplo. E permite também a criação de macros.

Isso nem sempre representa um benefício.

Outras vantagens que eu citaria para o C++ é a sobrecarga de operadores e a possibilidade de construção implícita, especialmente válida em aplicações mais matemáticas.

E

O que simplesmente abomino no C++ é o recurso de “#include”. Ele, basicamente, é que atende pelos tempos de compilação infernais de programas C++, e pela impossibilidade de você (dado um trecho de programa C++) saber se ele está sintaticamente correto sem fazer a compilação de todas as linhas anteriores. Isso é que faz com que IDEs para C++ não consigam um recurso de auto-complete ou “Intellisense” tão bom quanto as IDEs que lidam com o Java ou o C#.

J

Outra desvantagem do c++ no caso é o mecanismo de herança. Ele faz uma cópia exata dos dados da entidade antecessora, o que produz alguns inconvenientes como de o compilador não saber qual método usar(no caso herança múltipla), bem conhecido como Diamond Problem. Pode ser facilmente evitado com a palavra chave “virtual” ao se herdar entidades.

V

O diamond problem veio de uma interpretação perigosa que se tinha de herança, tanto que linguagens atuais a abominaram.
No C++, não existe o conceito forte de interfaces, você tem que contar com a boa vontade do programador para que o recurso saia direito.

O C++ também tem algumas bizarrices nesse quesito. Como herança private e, ainda mais estranho, herança protected.

Uma vantagem do Java é que a sintaxe ainda é muito nova, e portanto, não tem muitas exceções ou coisas esquisitas devido a necessidade de se manter compatibilidade com o passado.
Ela também já foi criada corrigindo os problemas do C++ e tornando padrão várias boas práticas que o C++ tem.

R

Pessoal:

Deixa eu aproveitar o gancho e me tirem uma dúvida: Qual a função da palavra friend? Se eu me lembro ela afeta o modo de acesso das variáveis/funçoes da mesma forma que public, protected ou private mas agora não me lembro como.

V

Se A diz que B é seu friend, então B poderá ver todas as partes privadas de A, como se fossem publicas.

É excelente para fazer DAOs. As classes podem dizer que seus DAOs são friends, para os daos tenham acesso total a seus atributos.
Esse modificador faz muita falta nessas horas.

R

ViniGodoy:
Se A diz que B é seu friend, então B poderá ver todas as partes privadas de A, como se fossem publicas.

É excelente para fazer DAOs. As classes podem dizer que seus DAOs são friends, para os daos tenham acesso total a seus atributos.
Esse modificador faz muita falta nessas horas.


Me dê um exemplo de como isso poderia ser feito em Java se existisse a palavra friend. Suponha que tenhamos as classes públicas UsuarioBusiness, UsuarioDAO e EmpresaBusiness. E daí eu quero que UsuarioDAO seja acessível apenas para UsuarioBusiness. Como faria?
Isso de restringir o acesso de classes não é o objetivo do projeto Jigsaw, agora prometido para o Java 8?

J

Friends podem ser tanto classes como funções.

Aqui no msdn existe um exemplo interessante a estilo do que o vini citou.

http://msdn.microsoft.com/en-us/library/ahhw8bzz.aspx

Apesar de eu achar a função friend quebrar o encapsulamento ela acaba sendo extremamente útil.

E

O motivo original de existirem “friends” em C++ é porque operadores normalmente são globais (ou então membros de uma classe, mas isso é mais raro).
Então você cria algo como:

class Complex {
private:
    double re;
    double im;
public:
    Complex (double re, double im) : re(re), im(im) { }
    friend Complex operator + (const Complex&, const Complex&);
};
...
// Note que isto é um operador global, mas precisa ter acesso aos membros da classe Complex,
// portanto ela tem de ser declarada como "friend" (amiga) da classe Complex. 
Complex operator + (const Complex& a, const Complex& b) {
    return Complex (a.re + b.re, a.im + b.im);
}
V

Você faria:

public class UsuarioBusiness {
  private int id;
  private String nome;

  //Indica que UsuarioDao é friend.
  friend class UsuarioDao;

  public int getId() { return id; }
  public String getNome() { return nome; }
}
public class UsuarioBusiness {
   public Usuario carregar(int id) {
      UsuarioBusiness usuario = new UsuarioBusiness();

       //Suponha que esse método existe, e acha o RowSet do usuário no banco.
      RowSet rs = loadFromDataBase(id);

      //Note que estou acessando propriedades privadas, como se fossem publicas
      //o hibernate e outras APIs fazem isso por reflexão. Aqui não há reflexão, há code completion e é tudo typesafe.
      usuario.id = rs.getInt("id"); 
      usuario.nome = rs.getString("nome"); 
      return usuario;
  }
}
J
Rafael Afonso:
ViniGodoy:
Se A diz que B é seu friend, então B poderá ver todas as partes privadas de A, como se fossem publicas.

É excelente para fazer DAOs. As classes podem dizer que seus DAOs são friends, para os daos tenham acesso total a seus atributos.
Esse modificador faz muita falta nessas horas.


Me dê um exemplo de como isso poderia ser feito em Java se existisse a palavra friend. Suponha que tenhamos as classes públicas UsuarioBusiness, UsuarioDAO e EmpresaBusiness. E daí eu quero que UsuarioDAO seja acessível apenas para UsuarioBusiness. Como faria?
Isso de restringir o acesso de classes não é o objetivo do projeto Jigsaw, agora prometido para o Java 8?

A seu Exemplo

#include <iostream>

using namespace std;
class UsuarioDao{
friend class UsuarioBusiness;  // aqui a classe friend
public:
   UsuarioDao() : topSecret(0){}
   void printMember() { cout << topSecret << endl; }
private:
   int topSecret;
};

class UsuarioBusiness{
public:
   void change( UsuarioDao& ub, int x ){ub.topSecret = x;}
};


int main() {
   UsuarioDao ud1;
   UsuarioBusiness ub1;
   ud1.printMember();
   ub1.change( ud1, 5 );
   ub1.printMember();
}

Me baseei no exemplo da msdn.

J

No final, a idéia é a do desenho abaixo

E

Em C++,
“O amigo de meu pai não é meu amigo”,
“O amigo de meu filho não é meu amigo”, e
“O amigo de meu amigo não é meu amigo”.

Eu chamaria o qualificador “friend”, na verdade, de “boyfriend” ou “girlfriend” (não sei qual é o sexo de uma classe) porque, de fato, o relacionamento em C++ está mais para esse tipo que o de amizade. Mas seria esquisito ter algo em C++ como:

public:
    partner Complex operator + (const Complex& a, const Complex& b);
J

entanglement:
O motivo original de existirem “friends” em C++ é porque operadores normalmente são globais (ou então membros de uma classe, mas isso é mais raro).
Então você cria algo como:

class Complex { private: double re; double im; public: Complex (double re, double im) : re(re), im(im) { } friend Complex operator + (const Complex&, const Complex&); }; ... // Note que isto é um operador global, mas precisa ter acesso aos membros da classe Complex, // portanto ela tem de ser declarada como "friend" (amiga) da classe Complex. Complex operator + (const Complex& a, const Complex& b) { return Complex (a.re + b.re, a.im + b.im); }

Isso mesmo. Se a sobrecarga de operador acontecer dentro do encapsulamento(da classe) você não pode usar o segundo parâmetro. Isso também mostra o que comentei sobre quebrar o encapsulamento, mesmo sendo muito útil.

Q

nesse caso por se tratar da própria classe as funções friends nem são necessárias, mas claro, fica a escolha do desenvolvedor, para classes matemáticas ele sempre me foi util quando se precisou sobrecarregar um operador onde o primeiro termo é um tipo primitivo. e.g.:

class Complex
{
	private:
	double r;
	double i;

	public:
	// para somar dois numeros complexos pode se fazer assim:
	virtual Complex operator +(Complex &);

	// o mesmo pode ser feito para somar um complexo com um double
	virtual Complex operator +(double &);

	// neste caso soma: Complex + double, mas ñ soma: double + Complex
	// para isso tem q usar uma função global, que ñ precisaria ser friend
	// mas o recurso ajuda a acessar os dados da classe Complex diretamente
	friend Complex operator +(double &, Complex &);
}

flw, t+

E

entanglement:
Em C++,

“O amigo de meu filho não é meu amigo”, e

Eu chamaria o qualificador “friend”, na verdade, de “boyfriend” ou “girlfriend” (não sei qual é o sexo de uma classe) porque, de fato, o relacionamento em C++ está mais para esse tipo que o de amizade.

A menos que você assista à novela das 8 e veja o que a Stela aprontou :slight_smile:

J

quikkoo:
nesse caso por se tratar da própria classe as funções friends nem são necessárias, mas claro, fica a escolha do desenvolvedor, para classes matemáticas ele sempre me foi util quando se precisou sobrecarregar um operador onde o primeiro termo é um tipo primitivo. e.g.:

class Complex
{
	private:
	double r;
	double i;

	public:
	// para somar dois numeros complexos pode se fazer assim:
	virtual Complex operator +(Complex &);

	// o mesmo pode ser feito para somar um complexo com um double
	virtual Complex operator +(double &);

	// neste caso soma: Complex + double, mas ñ soma: double + Complex
	// para isso tem q usar uma função global, que ñ precisaria ser friend
	// mas o recurso ajuda a acessar os dados da classe Complex diretamente
	friend Complex operator +(double &, Complex &);
}

flw, t+

Complex operator +(double &, Complex &)

Um compilador ansi/iso c++ não permitiria sobrecarregar + com dois parâmetros de dentro do escopo da classes, permitiria?
O g++ não permite comigo aqui.


E

Bom:

a) Se o operador é binário (operator + por exemplo), e se ele tem declarados 2 argumentos, então ele não recebe o argumento “this” implícito, portanto ele não pode ser membro de uma classe. Ele tem de ser estático ou global.

b) Se o operador é binário, e se ele tem declarado apenas 1 argumento, o outro argumento é o “this”. Nesse caso, ele é obrigado a ser membro de uma classe. É como se

Complex a;
Complex b;
Complex c = a + b;

nós tivéssemos algo como

c = (a. operator +) (b);
E

Note que um operador pode ser unário também. Por exemplo, digamos que queiramos criar um operador “-” para a classe Complex. Nesse caso, ou ele é declarado com 1 argumento e é global, ou ele é declarado sem argumentos e recebe implicitamente this.

J

entanglement:
Bom:

a) Se o operador é binário (operator + por exemplo), e se ele tem declarados 2 argumentos, então ele não recebe o argumento “this” implícito, portanto ele não pode ser membro de uma classe. Ele tem de ser estático ou global.

b) Se o operador é binário, e se ele tem declarado apenas 1 argumento, o outro argumento é o “this”. Nesse caso, ele é obrigado a ser membro de uma classe. É como se

Complex a;
Complex b;
Complex c = a + b;

nós tivéssemos algo como

c = (a. operator +) (b);


Com certeza.

Q

aqui compila normalmente e com o parametro ‘-ansi’, pois se trata de uma função idependente, e ñ um metodo da classe Complex, dai nao tem o primeiro parametro, que seria o this, como disse o entanglement

e nesse caso tem mesmo q compilar, pois pode-se colocar essa função (sobrecarga do operador +) fora da classe, mas daí ñ se pode usar o recurso friend

t+

J

quikkoo:
aqui compila normalmente e com o parametro ‘-ansi’, pois se trata de uma função idependente, e ñ um metodo da classe Complex, dai nao tem o primeiro parametro, que seria o this, como disse o entanglement

e nesse caso tem mesmo q compilar, pois pode-se colocar essa função (sobrecarga do operador +) fora da classe, mas daí ñ se pode usar o recurso friend

t+

sim, você tem razão. A palavra chave friend já implica que é apenas a declaração de um método que já existe.

M

Bem, aproveitando a thread, eu gostaria de saber se existe possibilidade de se conseguir a portabilidade em um aplicação com C++.

B

Baixe os fontes de uma aplicação C++ como o próprio JDK (em http://download.java.net/jdk6/source/ ).
Você vai ver que ele foi portado para as seguintes arquiteturas: x86, Sparc, x64, e ia64, tudo em um único fonte, para Windows, Linux e Solaris.
Obviamente isso demandou um monte de esforço (centenas de milhares de horas-homem de testes, desenvolvimento, especificação e gerenciamento).

Q

sim e não, tudo depende doq vc considera ser portável, e o quão portável vc deseja…

programas já compilados em c ou c++ geramente ñ funcionam em plataformas diferentes, e isso não é considerado portável, mas se vc considerar que uma recompilação sem qlqr alteração no código é algo portável, então temos um código em c ou c++, basta um conhecimento de quais bibliotecas usar em seu projeto para que isso aconteça

acho q portabilidade não é mais (ou nunca foi) um conceito onde é ou não é, mas sim até q ponto é portável, pois sobre certas circuntâncias nem mesmo códigos java e dot.net são portáveis, tem até uma brincadeira: “compile once, debug everywhere”

flw, t+

J

Sim, e posso te dizer que um fonte planejado, usando ansi/iso c++ pode rodar em uma gama de dispositivos muito maior que a do java.
Existem bibliotecas que se propõem a gerar interfaces portáveis como swing do java, que são os casos do wxwidgets e qt, além de muitas outras claro.

Não precisa muito esforço não.

A questão é claro, como os compiladores c++ geram instruções nativas, um executável win não vai rodar em ambiente linux. Então o que pode ser totalmente portável é o código fonte.

No final das contas essa é uma das funções do jit em uma máquina virtual.

http://www.wxwidgets.org/
http://qt.nokia.com/

B

Não se esquecer de:
a) Usar bibliotecas que foram portadas para vários sistemas operacionais e plataformas, como o Boost e o Qt,
b) O que não estiver na biblioteca e tiver de ser específico para um determinado sistema operacional deve ser segregado em uma classe separada,

Criado 25 de outubro de 2010
Ultima resposta 27 de out. de 2010
Respostas 32
Participantes 8