Perchè quando richiami la funzione CambiaColore passi già un oggetto di tipo Punto. Per essere precisi è un passaggio per riferimento; il riferimento "punta" alla memoria allocata per quell'oggetto.
Dovresti guardare i puntatori in C, il concetto è praticamente il medesimo.
Non è complesso concettualmente, vale anche per le variabili. Quando passi una variabile (magari di tipo int) per riferimento, stai passando l'indirizzo di quella variabile. Il valore della variabile, il numero che gli assegni per capirci, viene salvato all'indirizzo in cui si trova la variabile.
Per fare un esempio stupido:
Codice:
int a = 100; // Supponiamo che l'indirizzo sia 0x1234 (e.g. è espresso in esadecimale per comodità)
quando passi per riferimento questa variabile, viene passato l'indirizzo 0x1234. Quindi l'argomento della funzione riceve questo indirizzo e se apporta delle modifiche al valore della variabile (il nr. 100 dell'esempio) questo cambia anche per la funzione chiamante, perchè l'indirizzo a cui puntano è il medesimo.
Per spiegarmi meglio, considera questo esempio:
C++:
#include <iostream>
using namespace std;
void func(int &n, int m) {
cout << "Indirizzo di N in func() << " << &n << endl;
cout << "Indirizzo di M in func() << " << &m << endl;
n *= 2;
m *= 2;
}
int main() {
int n = 10;
int m = 10;
cout << "Valore di N: " << n << " indirizzo: " << &n << endl;
cout << "Valore di M: " << m << " indirizzo: " << &m << endl;
func(n, m);
cout << "N dopo moltiplicazione: " << n << "\nM dopo la moltiplicazione: " << m;
return 0;
}
Puoi eseguirlo direttamente da qui se preferisci:
http://cpp.sh/8z7fr
Output:
Codice:
Valore di N: 10 indirizzo: 0x71b09fa8f7f8
Valore di M: 10 indirizzo: 0x71b09fa8f7fc
Indirizzo di N in func() 0x71b09fa8f7f8
Indirizzo di M in func() 0x71b09fa8f7cc
N dopo moltiplicazione: 20
M dopo la moltiplicazione: 10
Guarda gli indirizzi: l'indirizzo della variabile N è uguale sia nel main() che nella funzione func(), mentre quello di M è diverso. Infatti noterai che il valore di N è stato moltiplicato per 2, mentre quello di M è rimasto uguale a prima.
Con gli oggetti è un pò più diverso, perchè quando crei un oggetto stai allocando della memoria nell'heap. In buona sostanza ti viene comunque restituito un puntatore a questa memoria. Ogni volta che crei un oggetto viene allocata della nuova memoria, in una locazione diversa da prima quindi, e viene restituito un puntatore a questa memoria.
Il concetto di passaggio per riferimento però è lo stesso, si tratta sempre del passaggio dell'indirizzo di memoria.
Quindi tornando al tuo caso: la variabile p del main e quella della funzione CambiaValore puntano alla medesima memoria, quindi se fai una modifica su quell'oggetto, questa modifica si vede anche nella funzione chiamante (ovvero nel main()).
Se crei un nuovo oggetto in CambiaColore stai effettivamente creando un altro oggetto, che quindi punterà a della memoria divesa dall'altro, e il tuo valore nel main sull'oggetto p rimarrà quello di prima.
Sono andato un pò di fretta, spero di essere stato chiaro.