2015-12-11 22 views
9

Mi chiedevo se potevo ignorare utilizzando getter se ho appena concesso una variabile di riferimento const, come seguePosso usare i riferimenti const invece delle funzioni getter?

#include <string> 

class cTest 
{ 
    private: 
     int m_i; 
     std::string m_str; 

    public: 
     const int & i; 
     const std::string & str; 

    cTest(void) 
    : i(m_i) 
    , str(m_str) 
    {} 
}; 

int main(int argc, char *argv[]) 
{ 
    cTest o; 
    int i = o.i; // works 
    o.i += 5; // fails 
    o.str.clear(); // fails 

    return 0; 
} 

Mi chiedo perché la gente non sembrano fare questo a tutti. C'è qualche grave svantaggio che mi manca? Si prega di contribuire alla lista dei vantaggi e degli svantaggi e correggerli se necessario.

Vantaggi:

  1. Non c'è sovraccarico attraverso chiamate di funzioni getter.
  2. La dimensione del programma diminuisce perché ci sono meno funzioni.
  3. Posso ancora modificare l'interno della classe, le variabili di riferimento forniscono uno strato di astrazione.

Svantaggi:

  1. Invece di funzioni getter, ho un sacco di riferimenti. Questo aumenta la dimensione dell'oggetto.
  2. Utilizzando const_cast, le persone possono incasinare membri privati, ma queste persone sono maliziose, giusto?

risposta

7

Alcuni svantaggi gravi anzi (a parte il secondo svantaggio che si parla anche che ho anche messo nella categoria "grave"):

1) È necessario fornire (e quindi mantenere) un copy constructor: il compilatore di default non funzionerà.

2) È necessario fornire un operatore di assegnazione: il predefinito del compilatore non funzionerà.

3) Pensare attentamente all'implementazione della semantica del trasferimento. Di nuovo, l'impostazione predefinita del compilatore non funzionerà.

Queste tre cose significano che l'anti-pattern di riferimento const che si propone è un non-starter. Non farlo!

+5

Per non parlare del giorno in cui si desidera utilizzare una rappresentazione più efficiente per i dati e non è possibile perché è necessario un riferimento valido a quei tipi. – chris

+0

@chris: Questo è un buon punto. Anche se hai una funzione che restituisce un riferimento const, puoi sempre refactoring che per restituire una copia valore dovrebbe cambiare il modello di dati. – Bathsheba

2

Un vantaggio delle funzioni getter è che potresti ad un certo punto nel tempo - desideri modificare il valore restituito - e senza la funzione getter non puoi farlo. Questo scenerio richiede di restituire effettivamente un riferimento non effettivo, che è meno comune in C++. [modifica] ma con la semantica del movimento invece dei riferimenti dovrebbe essere possibile [/ edit]

Si potrebbe anche voler inserire un punto di interruzione nella funzione getter per sapere chi sta leggendo il suo valore, si potrebbe voler aggiungere la registrazione, ecc. Si chiama incapsulamento .

Altro vantaggio di getter è che nelle build di debug è possibile aggiungere ulteriori assegni/asserzioni sui dati restituiti.

Nel compilatore finale verranno incorporate le funzioni getter, il che si tradurrà in un codice simile a quello che si propone.

qualche ulteriore svantaggio:

1) codice modello vorrà ottenere valori utilizzando la funzione di chiamata, vale a dire. size(), se lo si cambia in variabile & const non sarà possibile utilizzarlo in alcuni modelli. Quindi questo è un problema di coerenza.

0

Se si desidera evitare getter e setter, l'utilizzo di un membro di riferimento const non è la soluzione.

Invece, ti consigliamo di garantire la correttezza const sulla struttura circostante (che ti dà automaticamente accesso const ai membri), e solo lasciare che i membri siano ciò che devono essere logicamente.

Assicurarsi di leggere su quando getter e setter possono, dovrebbero o potrebbero essere scambiati con membri di dati pubblici. Vedi per es. this question. Basta notare che se si cambia l'interfaccia, il vantaggio annunciato di setter/getter è che chiamare il getter non influirà sui siti di chiamata. La realtà sembra discutere diversamente, e per es. refactoring di un membro insieme a tutti i suoi punti di accesso è un'operazione banale per qualsiasi editor di codice C++ che si rispetti.

Sebbene si possa argomentare per l'incapsulamento, io sostengo più fortemente la correttezza costante, che allevia la necessità di un sacco di incapsulamento e semplifica davvero molto il codice.

Problemi correlati