Esempio:
class Persona {
string nome;
int eta;
//costruttore
//metodo
Void saluta() {
System.out.println(“ciao, sono ” + nome);
}
}
Public class Main {
Public static void main (string[] args) {
Persona p = new Persona(“Anna”, 23);
// chiama il metodo -> “ciao, sono Anna”
p.saluta();
}
Differenza chiave:
- Costruttore = usato solo per inizializzare un nuovo oggetto
- Metodo = usato per far fare qualcoasa all’oggetto già esistente
[SOLO C++] Distruttore
Funzione public, ha lo stesso nome della classe ma con prefisso tilde ‘~’ (alt + 1 + 2 + 6)
Non ha né parametri né tipi di ritorno
Conviene usarlo quando utilizzo l’heap
Esempio:
class Persona {
Persona() { cout << “Costruttore chiamato\n”; }
~Persona() { cout << “Distruttore chiamato\n”; }
};
int Main() { // costruttore chiamato
Persona p;
// quando esce dallo scope -> distruttore chiamato
}
Static in java e C++
Serve per dire che qualcosa appartiene alla classe e non all’oggetto.
Significa che quel membro o metodo è condiviso da tutte le istanze della classe:
- variabile static / campo static → unica copia comune a tutti gli oggetti
class Persona { // campo static
static int contatore = 0;
Persona() { contatore++; }
}
ATTENZIONE: in Java spesso i termini variabile e campo si usano quasi come sinonimi, ma in
realtà il campo è un attributo dichiarato dentro la classe, mentre la variabile è un termine più
generico che può indicare una variabile locale (dentro un metodo), un parametro di metodo
oppure un campo (attributo di classe o di istanza).
- metodo static → si può chiamare senza creare un oggetto: classe.nomeMetodo();
class Matematica {
static int somma(int a, int b) { return a + b; }
} // chiamato senza new
Int x = Matematica.somma(2, 3);
In C++ static ha anche altri usi (variabili statiche locali, visibilità limitata nei file)
Modificatore Dove si usa Significato
public campi, metodi, classi visibile ovunque
private campi, metodi visibile solo nella classe
protected campi, metodi visibile a package + sottoclassi
(default) campi, metodi visibile solo a package
static campi, metodi appartiene alla classe, non agli oggetti
final variabili, metodi, classi non modificabile / non ereditabile
abstract classi, metodi obbligo di implementazione da sottoclassi
synchronized metodi un solo thread alla volta
volatile campi visibilità immediata tra thread
Aspetto Java C++
Ereditarietà Non supportata (usa interfacce) Supportata (più classi base)
multipla
Gestione Manuale (serve delete o smart
Garbage Collector automatico
memoria pointers)
Non visibili all’utente (solo
Puntatori Sì, puntatori e reference
reference)
Quasi tutto è dentro classi (anche Puoi avere funzioni globali fuori
Tutto in classi metodi statici) dalle classi
Modificatori Default → package-private (visibile Default → private
default nello stesso package)
Overloading Non possibile Possibile
operatori
Aspetto Java C++
Simili, ma in Java non esistono i C++ ha costruttori, distruttori, copy
Costruttori distruttori constructor
Tutti i metodi non-static sono Devi dichiarare virtual per avere
Metodi virtuali virtuali per default polimorfismo dinamico
Classe Object
In Java, Object è la superclasse di tutte le classi.
• Se non scrivi extends, la tua classe estende automaticamente Object.
• Contiene metodi base come:
• equals() // public boolean equals(Object obj)
o Concettualmente, equals restituisce true se il contenuto di due oggetti è
uguale (non il riferimento, come per l'operatore ==). Si richiede che implementi
una relazione di equivalenza, quindi che goda delle proprietà di riflessività,
simmetria, transitività e consistenza. Deve essere ridefinito in tutte le classi su
cui è necessario effettuare confronti.
Il metodo equals della classe Object, non potendo fare alcuna assunzione sulla
struttura interna degli oggetti su cui viene invocato, utilizza semlicemente
l'operatore == per confrontarli.
Quindi attenzione: se equals viene usato in una classe senza essere ridefinito,
non da' errore in esecuzione, ma il risultato potrebbe essere incorretto.
hashCode()
o toString() // public String toString()
o restituisce una stringa che puo' essere considerata come la "rappresentazione
testuale" dell'oggetto su cui e' invocato (da usare ad esempio nella stampa).
Deve essere ridefinito in ogni classe che lo usa, per ottenere un risultato
significativo (tipicamente, di un oggetto si vogliono stampare i valori delle
variabili d'istanza, ed eventualmente una intestazione).
Ecco perché qualunque classe appartiene sempre a Object.
Come personalizzare equals() (@Override)
Regole
• Riflessività: dev’essere sempre
x.equals(x) true
o Simmetria: e dev’essere uguale
x.equals(y) y.equals(x)
o Transitività: se e allora deve
x.equals(y) y.equals(z), x.equals(z)
o essere true
Consistenza: se nulla cambia, il risultato dev’essere sempre lo stesso
o Con deve restituire
null: x.equals(null) false
o
Struttura base dell’override
• @Override
public boolean equals(Object o) {
// 1. Se è lo stesso oggetto → true
if (this == o) return true;
// 2. Se è null o classi diverse → false
if (o == null || getClass() != o.getClass()) return false;
// 3. Cast dell’oggetto
MiaClasse other = (MiaClasse) o;
// 4. Confronto campi
return this.attributo1 == other.attributo1 &&
Objects.equals(this.attributo2, other.attributo2);
}
Scanner
Lo scanner è una classe di Java che serve a leggere input testuale (da tastiera, file, stringhe,
…).
Si trova nel package java.util, va importata → import java.util.Scanner;
Nel caso più comune (leggere da tastiera) si scrive:
Scanner sc = new Scanner(System.in);
Esempi utili:
1. Scanner sc = new Scanner(System.in);
System.out.print(“Inserisci una frase: ”);
String frase = sc.nextLine();
2. Scanner sc = new Scanner(System.in);
System.out.print(“Inserisci una numero intero: ”);
int n = sc.nextInt();
3. Scanner sc = new Scanner(System.in);
System.out.print(“Inserisci una numero decimale: ”);
double d = sc.nextDouble();
4. Scanner sc = new Scanner(System.in);
System.out.print(“Inserisci una numeri (0 per finire): ”);
while(sc.nextInt()) {
int n = sc.nextInt();
if(n == 0) break;
System.out.ptintln(“Hai inserito: ” + n);
}
Simbolo “:” in Java
In Java lo trovi nel costrutto del for-each:
for(Tipo variabile : collezione) {
// codice che usa variabile
}
Si legge “per ogni elemento della collezione”
Esempio:
int[] numeri = {1, 2, 3};
for(int n : numeri) {
System.out.println(n);
}
[C++] Posizione di const
ATTENZIONE: “const” si usa in C++, in Java si usa “final” ma in modo diverso!
- const int f();
significa che la funzione ritorna un valore costante.
Il valore che ricevi non lo puoi modificare se è un riferimento o un puntatore.
Esempio:
const string& getName();
- void f(const int x);
Significa che il parametro è costante dentro la funzione.
Se provi a scrivere x = 5 → errore
Esempio:
void stampa(const string& s){
//posso leggerla
cout << s << endl;
//s = “ciao”; //errore
}
- int f() const;
Questo riguarda i metodi delle classi, significa: “questo metodo non può modificare i
campi (variabili membro) dell’oggetto”
Esempio:
class Persona{
string nome;
public:
string getNome() const{
return nome;
}
Void setNome(string nuovo){
nome = nuovo;
}
};
Se provassi:
string getNome() const{ //ERRORE
nome = “altro”;
return nome;
}
Scope (ambito)
Lo scope è l’area del codice in cui una variabile è visibile e valida.
Quando una variabile esce dallo scope, la sua memoria viene automaticamente
• liberata (se è in stack, vedi sotto).
Questo vale per variabili locali e oggetti creati “senza new”.
•
Stack vs Heap
La memoria di un programma C++ è divisa in zone, le più importanti per noi sono:
Stack → gestito automaticamente
• Heap → gestito manualmente
•
Stack Memoria automatica
• Usata per variabili locali, parametri di funzione, return temporanei
• Viene liberata automaticamente alla fine dello scope
• Molto veloce, ma dimensione limitata
•
Heap Memoria dinamica
• Devi gestirla tu (o con smart pointer)
• Usata con new / new[] per creare oggetti che vivono oltre lo scope corrente
• Più lenta dello stack ma più flessibile (puoi creare oggetti grandi e decidere quanto
• restano in vita)
Devi liberarla con delete / delete[] o smart pointers
•
Relazione con i distruttori
Oggetti nello stack → il distruttore viene chiamato automaticamente quando escono
• dallo scope.
Oggetti nell’heap → il distruttore viene chiamato solo quando usi delete (o lo smart
• pointer decide di distruggere l’oggetto).
Vita variabili
Allocazione statica: deallocazione al termine del programma -> DATA SEGMENT
• Allocazione automatica: deallocazione al termine del blocco -> STACK
• Allocazione dinamica: deallocazione tramite l’operatore delete -> HEAP
•
Vita oggetti: visti come un’allocazione automatica (è presente un distruttore), tempo di
esecuzione del blocco
Overloading operatore di assegnamento
Va fatto altrimenti due oggetti con variabili allocate dinamicamente punteranno allo stesso
indirizzo in memoria.
L'overload dell'operatore di assegnazione in C++ (e in altri linguaggi) permette di definire il
comportamento dell'operatore "=" quando viene utilizzato con tipi di dati definiti
dall'utente. In pratica, si può ridefinire il modo in cui gli oggetti di una classe vengono
assegnati ad altri oggetti della stessa classe o di tipi diversi.
Quando si lavora con puntatori o risorse dinamiche all'interno di una classe, l'assegnazione di
default potrebbe non essere sufficiente o potrebbe portare a problemi di memoria (ad
esempio, copie superficiali di puntatori, perdite di memoria). L'overload permette di
implementare una copia profonda, allocando nuova memoria per i dati e copiando i
contenuti.
Scarica il documento per vederlo tutto.
Scarica il documento per vederlo tutto.
Scarica il documento per vederlo tutto.
Scarica il documento per vederlo tutto.
Scarica il documento per vederlo tutto.
Scarica il documento per vederlo tutto.
Scarica il documento per vederlo tutto.
Scarica il documento per vederlo tutto.
-
Fondamenti di programmazione - Appunti
-
Appunti Fondamenti Informatica B
-
Istologia – Fondamenti
-
Raggi – Fondamenti