Operatori di Accesso ai Membri in C++
- Gli operatori di accesso ai membri in C++ forniscono un modo per accedere ai membri di una classe o struttura.
- L'operatore punto (
.
) viene utilizzato per accedere ai membri di un oggetto. - L'operatore freccia (
->
) viene utilizzato per accedere ai membri di un oggetto tramite un puntatore. - La dereferenziazione di un puntatore ha una precedenza inferiore rispetto all'operatore punto.
- L'operatore freccia richiede un operando puntatore e produce un l-value.
- L'operatore punto produce un l-value se l'oggetto da cui viene recuperato il membro è un l-value; altrimenti il risultato è un r-value.
Gli Operatori di Accesso ai Membri
Gli operatori punto .
e freccia ->
forniscono l'accesso ai membri di una struttura o classe. L'operatore punto recupera un membro da un oggetto di tipo classe; la freccia è definita in modo tale che ptr->membro
sia un sinonimo di (*ptr).membro
:
string s1 = "a string", *p = &s1;
// Invoca la funzione membro (metodo) della string s1
auto n = s1.size();
// Invoca la funzione membro (metodo) dell'oggetto a cui p punta
n = (*p).size();
// equivalente a (*p).size()
n = p->size();
Poiché la dereferenziazione ha una precedenza inferiore rispetto al punto, dobbiamo mettere tra parentesi la sottoespressione di dereferenziazione. Se omettiamo le parentesi, questo codice significa qualcosa di molto diverso:
// esegue il membro size di p, poi dereferenzia il risultato!
// ERRORE: p è un puntatore e non ha un membro chiamato size
*p.size();
Questa espressione tenta di recuperare il membro size
dell'oggetto p
. Tuttavia, p
è un puntatore, che non ha membri; questo codice non compilerà.
L'operatore freccia richiede un operando puntatore e produce un l-value. L'operatore punto produce un l-value se l'oggetto da cui viene recuperato il membro è un l-value; altrimenti il risultato è un r-value.
Esercizi
-
Assumendo che
iter
sia unvector<string>::iterator
, indica quali, se ce ne sono, delle seguenti espressioni sono legali. Spiega il comportamento delle espressioni legali e perché quelle che non sono legali sono in errore.*iter++;
Soluzione: Questa espressione è legale. L'operatore di post-incremento
++
ha una precedenza più alta rispetto all'operatore di dereferenziazione*
. Quindi, l'espressione viene interpretata come*(iter++)
. Questo significa che l'iteratoreiter
viene incrementato ma una sua copia (il valore prima dell'incremento) viene passata all'operatore di dereferenziazione. In altre parole, l'operatore*
restituisce l'elemento corrente a cuiiter
puntava prima dell'incremento, maiter
stesso viene spostato al prossimo elemento.(*iter)++;
Soluzione: Questa espressione non è legale perché tenta di incrementare un oggetto di tipo
string
. L'operatore di post-incremento++
non è definito per il tipostring
, quindi questa espressione causerà un errore di compilazione.*iter.empty();
Soluzione: Questa espressione non è legale. L'operatore di dereferenziazione
*
ha una precedenza più bassa rispetto all'operatore di accesso ai membri.
. Quindi, l'espressione viene interpretata come*(iter.empty())
. Tuttavia,iter
è un iteratore e non ha un membro chiamatoempty()
. Questo causerà un errore di compilazione.iter->empty();
Soluzione: Questa espressione è legale. L'operatore di accesso ai membri
->
viene utilizzato per accedere al membroempty()
della stringa a cuiiter
punta. La funzioneempty()
restituisce un valore booleano che indica se la stringa è vuota o meno.++*iter;
Soluzione: Questa espressione non è legale perché tenta di incrementare un oggetto di tipo
string
. L'operatore di pre-incremento++
non è definito per il tipostring
, quindi questa espressione causerà un errore di compilazione.iter++->empty();
Soluzione: Questa espressione è legale. Qui, l'operatore di post-incremento
++
viene applicato aiter
, che è un iteratore. L'operatore->
viene quindi utilizzato per accedere al membroempty()
della stringa a cuiiter
puntava prima dell'incremento. La funzioneempty()
restituisce un valore booleano che indica se la stringa è vuota o meno.