Newsgroup: it.comp.java
Titolo: Java contro C++

Che differenze ci sono fra C++ e Java ???
                            Robert

Che differenze ci sono fra C++ e Java ???
Tantissime...!!!  Al di la` di qualche somiglianza superficiale
(in massima parte riportabile alla comune radice C), sono due
linguaggi drasticamente differenti.  Non ho certo lo spazio
per elencare tutte le differenze (a parte lo zucchero sintattico,
ce ne vorrebbe circa altrettanto per dare le differenze fra
Fortran e Pascal...:-), ma, eccone alcune.
In C++ esistono dichiarazioni e definizioni -- come in C, sono
due cose separate; da una parte (normalmente un header file)
io scrivo una dichiarazione, tipo quella di una funzione globale:
    int pippo(int);
e, da un'altra parte, in un file sorgente, la definizione:
    int pippo(int pluto) { return pluto+23; }
Queste "cose", che da una parte dichiaro e da un'altra definisco,
sono: funzioni e variabili globali, funzioni e variabili locali ad un
certo file ("static", o, in C++ Standard, unnamed-namespace),
funzioni ("metodi") e variabili ("membri") interni a una certa classe
(static o meno), variabili (non funzioni) interne a un certo blocco.
In Java: non esiste la separazione fra dichiarazione e definizione,
non esistono funzioni o variabili globali, non esistono funzioni o
variabili locali a un certo file -- solo metodi e membri di classi,
static o meno, definiti contestualmente alla dichiarazione, e
variabili interne a un certo blocco.
Fra i tipi elementari: Java non ha unsigned (numeri senza segno),
struct, union, puntatori e reference (almeno non esplicitamente).
In C++, posso avere dati di qualsiasi tipo in registri, stack ("auto"), 
heap (con "new") e aree statiche ("static" e globali).  Java invece
ha sempre in stack (o aree statiche) i tipi elementari e le implicite
reference a oggetti e array -- gli array e oggetti stessi possono
vivere solo in heap (allocati con "new").  In C++ sono per default
inizializzati tutti gli oggetti, ma solo quei dati elementari che vivono
in aree statiche; in Java, tutti i dati (e implicite reference a oggetti
e array) sono sempre inizializzati.  Gli argomenti alle funzioni C++
possono essere passati per valore, per indirizzo, o per reference
(eccetto gli array, che automaticamente sono per indirizzo); in Java,
sono passati automaticamente per valore i dati elementari, e, si puo`
dire, per reference gli array e gli oggetti.
Java non ha distruttori, quindi non si puo` far conto sul cruciale
idioma C++ per cui una risorsa e` incapsulata da una classe che
la acquisisce nel costruttore e la rilascia nel distruttore; in Java,
e` invece cruciale, come in C, fare il rilascio esplicito di tutte le
risorse acquisite -- con l'eccezione della memoria (allocata con
"new"), che e` l'unica risorsa a venire liberata in modo implicito
(mentre in C++ bisogna garantire che qualcuno, tipicamente il
distruttore di un altro oggetto "padrone", la rilasci).
In C++ si possono avere eredita` singola o multipla, diretta o
virtuale; in Java, l'eredita` "vera e propria" e` singola e diretta,
mentre un meccanismo analogo ma distinto permette di avere
l'equivalente dell'eredita` multipla (e virtuale) ma solo per le
"interfacce" (che sono come classi "vuote", che cioe` non
implementano i metodi che dichiarano -- questo effetto si puo`
avere anche in C++, ma con granularita` assai maggiore, cioe`
decidendo metodo per metodo, e senza precludere alle
"classi astratte" cosi` ottenute di contenere dati -- anche Java
permette di fare classi astratte con parziali implementazioni,
ma ereditare da una di esse impedisce qualsiasi altra eredita`).
Inoltre in Java tutti gli oggetti implicitamente ereditano da una
singola classe speciale "Object", mentre in C++ non ci sono
vincoli sull'avere diversi "alberi" separati (d'altronde unibili
"alle foglie" per eredita` multipla).  Java permette al programmatore
di vietare ulteriore eredita`/ridefinizione dichiarando un metodo
o una classe "final"; C++ non ha diretto supporto per questi
concetti (anche se in parte possono essere ottenuti con l'uso
di altri meccanismi del linguaggio).  Viceversa, il C++ permette
di dichiarare che certi oggetti non devono venire modificati
("const"); Java non ha diretto supporto per questo concetto.
C++ ha un ricco sistema di "programmazione generica", ovvero
"template"; Java non ha nessun meccanismo equivalente.
Java ha supporto built-in per il multi-threading, la persistenza,
e l'analisi a run-time delle caratteristiche di oggetti e classi (che
possono essere caricate dinamicamente); il C++ non ha, a livello
di linguaggio, quasi nessun meccanismo del genere, e deve
quindi affidarsi interamente a librerie esterne per queste funzioni.
Le librerie standard Java sono ricchissime, e in particolare
comprendono (al livello Java 1.2) tre diversi schemi, non del
tutto compatibili, di GUI (graphical user interface); il C++ ha
librerie standard piu` ricche in certe aree (strutture-dati e
algoritmi) ma totalmente assenti in altre (nessuna GUI nelle
librerie standard C++ -- si fa totale affidamento su librerie
esterne).  Similmente per il supporto di rete (socket, HTML,
invocazione di metodi remoti, ecc) -- Java ha librerie ricche
e complesse come parte dello standard del linguaggio, C++
si affida interamente a librerie esterne al suo standard.
Vabbe` -- essendo ragionevolmente esperto nella teoria e
nell'uso di entrambi i linguaggi, potrei andare avanti per ore.
Vantaggi e svantaggi sono moltissimi da entrambe le parti.
Riassumendo, e nel complesso: il C++ permette a chi lo
usa per programmare di fare "assolutamente di tutto" -- il
che lo rende un linguaggio molto complicato e difficile da
usare, proprio perche` e` cosi` ricco, cosi` articolato, cosi`
pieno di decisioni da prendere per chi ci programma; e` da
dire, naturalmente, che, se tutte queste decisioni il programmatore
le prende in modo ottimale, in C++ potra` ottenere codice
assolutamente perfetto per le sue esigenze -- ma non senza
fatica e sudore della fronte.
Java e`, a parita` di esperienza e di conoscenza di entrambi
i linguaggi, piu` facile da usare bene e senza errori; inoltre, se
si deve scegliere, e` meno lavoro arrivare a padroneggiare il
linguaggio Java, che non il C++ (la situazione puo` essere
diversa per le librerie standard, che in Java sono ricchissime;
ma per scrivere programmi di funzionalita` equivalente in C++,
bisognera` comunque impadronirsi di librerie analoghe).
Per la maggior parte dei programmatori, C++ e` troppo difficile
per arrivare alla padronanza totale, Java probabilmente non lo
e`; per la maggior parte dei programmi, le limitazioni di Java
rispetto al C++ non si fanno d'altronde sentire piu` che tanto
(con l'unica eccezione della mancanza della programmazione
generica, che E` una grossa scocciatura per l'esperto C++ che
utilizza Java -- la programmazione generica e` MOLTO comoda
e pratica... c'e` un compilatore sperimentale, chiamato mi pare
GJ e realizzato da un'universita`, che permette di usare la
programmazione generica in quello che, per il resto, e` un
ambiente Java standard -- cosi`, tanto per provare, puo` meritare
"assaggiarlo").  Penso quindi che, per la grande maggioranza
di coloro che oggi usano C++ o si chiedono se studiarlo,
potrebbe essere meglio scegliere invece Java, almeno per
la gran parte delle applicazioni; conoscere e usare, quando
e come appropriato, entrambi i linguaggi (e altri ancora, certo,
per usi diversi, come ad esempio lo "scripting") potrebbe poi
essere la soluzione ottimale per quei programmatori che sono
in effetti in grado di impadronirsi di entrambi e gestirli al meglio.
E` difficile pensare a un caso in cui l'optimum sia di imparare e
usare solo ed esclusivamente il C++.
Alex