Esercizi di Lettura Codice - Oggetti in C++
Esercizio 1
Domanda: Il seguente programma compila ed esegue? Cosa stampa? Spiega la differenza tra passaggio per valore e per riferimento degli oggetti.
#include <iostream>
using namespace std;
class Punto {
public:
int x, y;
Punto(int a, int b) : x(a), y(b) {}
void sposta(int dx, int dy) {
x += dx; y += dy;
}
};
void spostaPerValore(Punto p) {
p.sposta(10, 10);
}
void spostaPerRiferimento(Punto& p) {
p.sposta(10, 10);
}
int main() {
Punto p(1, 1);
spostaPerValore(p);
cout << "Dopo spostaPerValore: (" << p.x << ", " << p.y << ")" << endl;
spostaPerRiferimento(p);
cout << "Dopo spostaPerRiferimento: (" << p.x << ", " << p.y << ")" << endl;
return 0;
}
Esercizio 2
Domanda: Osserva il seguente codice. Quante volte viene chiamato il costruttore e il distruttore? Qual è l’ordine di chiamata? Spiega cosa succede.
#include <iostream>
using namespace std;
class Test {
public:
Test() { cout << "Costruttore\n"; }
~Test() { cout << "Distruttore\n"; }
};
void funzione() {
Test t;
cout << "Dentro funzione\n";
}
int main() {
cout << "Inizio main\n";
funzione();
cout << "Fine main\n";
return 0;
}
Esercizio 3
Domanda: Il metodo getX è dichiarato const. Cosa significa? Il codice compila? Cosa succede se proviamo a modificare x dentro getX?
#include <iostream>
using namespace std;
class Punto {
int x, y;
public:
Punto(int a, int b) : x(a), y(b) {}
int getX() const {
// x = 10; // Cosa succede se decommentiamo questa riga?
return x;
}
};
int main() {
Punto p(5, 6);
cout << p.getX() << endl;
return 0;
}
Esercizio 4
Domanda: Il seguente programma utilizza un oggetto come parametro e come valore di ritorno. Cosa stampa? Spiega il comportamento del ritorno per valore.
#include <iostream>
using namespace std;
class Numero {
int val;
public:
Numero(int v) : val(v) {}
Numero raddoppia() {
return Numero(val * 2);
}
int getVal() const { return val; }
};
Numero modifica(Numero n) {
return n.raddoppia();
}
int main() {
Numero n(3);
Numero m = modifica(n);
cout << "n: " << n.getVal() << ", m: " << m.getVal() << endl;
return 0;
}
Esercizio 5
Domanda: Considera la classe ArrayDinamico. Il programma compila? Cosa succede alla fine del main? Spiega il problema relativo al copy constructor implicito.
#include <iostream>
using namespace std;
class ArrayDinamico {
int* dati;
int size;
public:
ArrayDinamico(int s) : size(s) {
dati = new int[size];
for(int i=0; i<size; i++) dati[i] = i;
cout << "Costruttore chiamato\n";
}
~ArrayDinamico() {
delete[] dati;
cout << "Distruttore chiamato\n";
}
void stampa() {
for(int i=0; i<size; i++) cout << dati[i] << " ";
cout << endl;
}
};
void funzione(ArrayDinamico a) {
a.stampa();
}
int main() {
ArrayDinamico arr(5);
funzione(arr);
arr.stampa();
return 0;
}
Esercizio 6
Domanda: Nel seguente codice, la variabile membro val è ombreggiata dal parametro del costruttore. Il codice compila? Qual è il valore di val dopo la costruzione? Come correggere il problema?
#include <iostream>
using namespace std;
class Valore {
int val;
public:
Valore(int val) {
val = val;
}
int getVal() const { return val; }
};
int main() {
Valore v(10);
cout << v.getVal() << endl;
return 0;
}
Esercizio 7
Domanda: Il seguente codice mostra un esempio di copy constructor personalizzato per una classe con risorsa dinamica. Spiega cosa succede se non fosse definito. Cosa stampa il programma?
#include <iostream>
using namespace std;
class Stringa {
char* s;
public:
Stringa(const char* str) {
int len = 0;
while(str[len] != '\0') len++;
s = new char[len + 1];
for(int i=0; i<=len; i++) s[i] = str[i];
cout << "Costruttore\n";
}
Stringa(const Stringa& other) {
int len = 0;
while(other.s[len] != '\0') len++;
s = new char[len + 1];
for(int i=0; i<=len; i++) s[i] = other.s[i];
cout << "Copy constructor\n";
}
~Stringa() {
delete[] s;
cout << "Distruttore\n";
}
void stampa() const {
cout << s << endl;
}
};
Stringa creaStringa() {
Stringa temp("ciao");
return temp;
}
int main() {
Stringa s1 = creaStringa();
s1.stampa();
return 0;
}