Ci sono diversi motivi per cui restituire riferimenti (o puntatori) ai componenti interni di una classe sono errati. A partire da (quello che io ritengo essere) il più importante:
incapsulamento è violato: Hai perdite un dettaglio di implementazione, il che significa che non è più possibile modificare le parti interne di classe come si desidera. Se hai deciso di non memorizzare first_
ad esempio, ma per calcolarlo al volo, come restituiresti un riferimento? Non puoi, quindi sei bloccato.
Invariant non sono più sostenibili (in caso di riferimento non const): chiunque può accedere e modificare l'attributo di cui a volontà, quindi non è possibile "controllare" i suoi cambiamenti. Significa che non puoi mantenere un invariante di cui questo attributo è parte. In sostanza, la tua classe si sta trasformando in un blob.
Lifetime problemi di avviamento: è facile mantenere un riferimento o un puntatore all'attributo dopo che l'oggetto originale a cui appartengono ha cessato di esistere. Questo è ovviamente un comportamento indefinito. La maggior parte dei compilatori tenterà di mettere in guardia sul mantenimento dei riferimenti agli oggetti nello stack, ad esempio, ma non conosco alcun compilatore che sia riuscito a produrre tali avvisi per i riferimenti restituiti da funzioni o metodi: sei da solo.
Come tale, di solito è meglio non dare riferimenti o riferimenti agli attributi. Neanche costosi!
Per piccoli valori, è generalmente sufficiente passarli copiando (sia in
e out
), specialmente ora con la semantica di movimento (sul fondo).
Per valori più grandi, dipende molto dalla situazione, a volte un proxy può alleviare i tuoi problemi.
Infine, si noti che per alcune classi, avere membri pubblici non è così male.Quale sarebbe il punto di incapsulare i membri di un pair
? Quando ti ritrovi a scrivere una classe che non è altro che una collezione di attributi (non invariante di sorta), allora invece di prendere tutto OO su di noi e scrivere una coppia getter/setter per ognuno di essi, considera la possibilità di renderli pubblici.
fonte
2011-11-04 07:25:40
+1, ma esiste una controproposta logica per fornire gli accessor: è possibile aggiungere una strumentazione alla chiamata e questo rende più facile trovare i luoghi in cui l'oggetto viene aggiornato nel codice o collegare un debugger per rilevare i problemi. –
Per informazioni, l'esempio parlava di classi che hanno membri privati quindi 'bool deleted_;'. Mi piace POD –
@David: non sono contro accessors come in 'T get()/void set (T)', in cui puoi tracciare efficacemente i cambiamenti dei tuoi valori, fornire il calcolo lazy e molte altre cose, ma il solo un interessante tidbit in un 'T & access()' significa "tracciare" che è stato effettuato un accesso, il che non porta molto alla tabella. –