Secondo me, le risposte esistenti fanno un pessimo lavoro nello spiegare il "perché" di questo - concentrandosi troppo sul ribadire quale comportamento sia valido. "i modificatori di accesso funzionano a livello di classe e non a livello di oggetto." - si ma perché?
Il concetto generale qui è che sono i programmatori che progettano, scrivono e mantengono una classe che devono comprendere l'incapsulamento OO desiderato e autorizzato a coordinarne l'implementazione. Quindi, se stai scrivendo class X
, stai codificando non solo come un singolo X x
oggetto può essere utilizzato dal codice con accesso ad esso, ma anche come:
- le classi derivate sono in grado di interagire con esso (tramite funzioni virtuali opzionali pure e / o accesso protetto), e
X
oggetti distinti cooperano per fornire i comportamenti previsti rispettando le post-condizioni e le invarianti dal tuo progetto.
Non è nemmeno solo il costruttore di copie: molte operazioni possono coinvolgere due o più istanze della tua classe: se stai confrontando, aggiungendo / moltiplicando / dividendo, costruendo copie, clonando, assegnando ecc., Allora è spesso il caso che tu o semplicemente deve avere accesso a dati privati e / o protetti nell'altro oggetto, o desidera che consenta un'implementazione della funzione più semplice, più veloce o generalmente migliore.
In particolare, queste operazioni potrebbero voler sfruttare l'accesso privilegiato per fare cose come:
- (costruttori di copia) usano un membro privato dell'oggetto "rhs" (lato destro) in un elenco di inizializzatori, in modo che una variabile membro sia essa stessa costruita in copia invece che costruita in modo predefinito (se anche legale) e quindi assegnata (di nuovo, se legale)
- condividere risorse: handle di file, segmenti di memoria condivisa, messaggi
shared_ptr
di posta elettronica per fare riferimento ai dati ecc
- assumere la proprietà delle cose, ad esempio
auto_ptr<>
"sposta" la proprietà sull'oggetto in costruzione
- copiare "cache" privata, calibrazione o membri di stato necessari per costruire il nuovo oggetto in uno stato utilizzabile in modo ottimale senza doverli rigenerare da zero
- copia / accedi alle informazioni di diagnostica / traccia conservate nell'oggetto che viene copiato che non sono altrimenti accessibili tramite API pubbliche ma potrebbero essere utilizzate da qualche oggetto di eccezione o logging successivo (ad esempio qualcosa sul tempo / le circostanze in cui l'istanza "originale" non costruita dalla copia fu costruito)
- eseguire una copia più efficiente di alcuni dati: ad esempio, gli oggetti possono avere, ad esempio, un
unordered_map
membro ma esporre pubblicamente solo begin()
e end()
iteratori - con accesso diretto a size()
voi potrebbe essere possibile reserve
una copia più rapida; peggio ancora se solo espongono at()
e insert()
ed altro throw
....
- copiare i riferimenti agli oggetti padre / coordinamento / gestione che potrebbero essere sconosciuti o di sola scrittura per il codice client