=====const===== La parola chiave ''const'' può essere usata per indicare al compilatore che una certa variabile non deve essere più modificata una volta che è stata inizializzata, oppure per dichiarare metodi di una classe che non possono alterare alcuna variabile membro della stessa classe. =====Uso===== Una pratica corretta nell'uso di ''const'' è quella di usarlo per proteggere dati che non devono essere sovrascritti. Questo deve essere fatto nella fase di progettazione poiché forzare un ''const'' in un programma dopo che ha già raggiunto uno stadio di maturazione dello sviluppo avrebbe considerevoli effetti a cascata. La parola ''const'' può assumere molti significati, può essere usata in numerose posizioni della sintassi (anche in alcune piuttosto innaturali) ====Dichiarazioni==== Per capire cosa ''const'' sta proteggendo bisogna leggere da destra a sinistra. const char * str; // puntatore a caratteri che non possono essere cambiati (anche se il puntatore può cambiare) char const * str; // come prima, solo un modo alternativo per scriverlo char * const str; // il puntatore non può essere modificato (anche se i caratteri nel buffer possono cambiare) Analogamente per le //reference// (non ha senso applicare un ''const'' a una reference, dato che il senso stesso delle reference è che non possono essere cambiate per riferire ad un altro oggetto): const char & str; // reference verso un carattere che non può essere cambiato char const & str; // funziona come alla riga precedente Finora sembra abbastanza semplice, ma costruzioni più complicate possono essere difficili da interpretare. Esempio: char * const * data; // puntatore ad un puntatore non modificabile che punta ad un array di caratteri char const ** data; // puntatore ad un puntatore di caratteri non modificabili const char ** data; // puntatore ad un puntatore di caratteri non modificabili char ** const data; // puntatore non modificabile che punta ad un puntatore di caratteri char * const * const data; // puntatore non modificabile verso un puntatore non modificabile di caratteri Esiste tra alcuni programmatori la convinzione che sia obbligatorio mettere ''const'' dopo il tipo dati, ma in realtà può essere scritto sia prima che dopo il tipo, se è un tipo dati regolare e non un puntatore (e.g. "char"). Usate la forma che si adatta meglio al vostro codice e agli standard di sviluppo del codice adottati dalla vostra organizzazione semplicemente cercando di essere consistenti. Se volete che ''const'' si applichi al puntatore la parola chiave deve apparire dopo l'asterisco. E' inoltre una buona pratica dichiarare certi campi di un oggetto come ''const'' se questi esprimono una proprietà dell'oggetto che non cambierà durante la vita di esso. ====Parametri==== L'uso più comune di ''const'' è di proteggere dati da cambiamenti che potrebbero essere fatti tramite puntatori o reference void func ( const MyObject * data ); // MyObject non può essere cambiato in func void func ( const MyObject & data ); // MyObject non può essere cambiato in func Notate che il posizionamento di const prima o dopo è irrilevante. Le righe seguenti sono equivalenti a quelle scritte sopra void func ( MyObject const * data ); // uguale a ( const MyObject * ) void func ( MyObject const & data ); // uguale a ( const MyOjbect & ) Posizionare ''const'' dopo il puntatore o la reference cambia i suoi effetti. Un ''const'' che segue il puntatore cambia solo il puntatore, non i dati che questo punta. void func ( MyObject * const data ); // Protezione superflua di 'data' poiché passato per valore All'interno di func siete liberi di manipolare MyObject, ma non il puntatore a MyObject. Tuttavia, siccome il puntatore è una variabile locale della funzione questo non è di grande utilità. Anche se cambiaste il valore del puntatore nulla verrebbe alterato al di fuori della funzione. Posizionare const dopo una reference è completamente inutile e deve essere evitato. Le reference sono già implicitamente ''const'' void func ( MyObject & const data ); // protezione inutile della reference a MyObject In questo caso const protegge la reference, che non può venir manipolata. A volte è utile ritornare dati privati di un oggetto preservando la loro non modificabilità al di fuori di esso. const MyObject & MyClass::func ( MyObject & data ); // l'oggetto MyObject ritornato da func non può essere cambiato ====Metodi==== Spesso metodi di un istanza non manipolano dati interni all'oggetto. Questi metodi (spesso chiamati //accessors//) dovrebbero essere dichiarati ''const'' L'effetto di questo è che il puntatore [[this]] all'interno del metodo, invece di essere definito come "MyClass *" sarà un "const MyClass *" così che l'oggetto non può essere modificato tramite questo puntatore. void MyClass::func ( MyOjbect & data ) const; // Questa funzione non manipola dati della classe Da notare che dichiarare un oggetto come ''const'' funziona come filtro sulla sua interfaccia dato che solo i metodi dichiarati ''const'' possono essere chiamati. Il motivo è legato a quanto già detto: chiamare un metodo di un oggetto 'const' significa passare implicitamente un puntatore all'oggetto di tipo "const MyClass *" e quindi un puntatore di un oggetto non modificabile. void MyClass::const_func() const; void MyClass::func(); const MyClass object; object.const_func(); // ok object.func(); // non si può chiamare un metodo non-const di un oggetto const Per la stessa ragione all'interno di un metodo ''const'' si può chiamare solo altri metodi ''const'' dell'oggetto. Argomenti correlati: [[const_cast]], [[mutable]]