Domanda

Ho un membro della classe MyMember che è un myType puntatore. Voglio assegnare a questo utente in una funzione che viene dichiarata come const. Sto facendo come segue:

void func() const
{
     ...
     const_cast<myType*>(myMember) = new myType();
     ...
}

In questo modo funziona bene in VC ++, ma GCC dà un errore con il messaggio "lvalue richiesto come operando a sinistra di assegnazione".

Fare il membro mutevole mi permetta di rimuovere semplicemente il const_cast e assegnare il valore. Tuttavia, non sono del tutto sicuro che che viene fornito con altri effetti collaterali.

Posso assegnare il mio membro, senza dover fare il membro mutevole? Come? Ci sono effetti collaterali a fare i membri mutevole?

È stato utile?

Soluzione

Il codice di solito in realtà lavorano in VC ++ - non state aggiornando il valore (o almeno Non dovrebbe), da qui l'avvertimento da GCC. codice corretto è

const_cast<myType*&>(myMember) = new myType();

o [da altra risposta, grazie: P]:

const_cast<ThisType*>(this)->myMember = new myType();

Rendendo mutabili in modo efficace significa che si ottiene const_casts impliciti in funzioni membro const, che è generalmente quello che dovrebbe essere dirigendo verso quando vi trovate a fare i carichi di const_casts su this. Non ci sono 'effetti collaterali di utilizzare mutabile' diverso da quello.

Come si può vedere dai dibattiti veementi che circondano questa domanda, l'utilizzo volenti o nolenti di mutable e un sacco di const_casts può sicuramente essere sintomi di cattivi odori nel codice. Da un punto di vista concettuale, gettato via constness o utilizzando mutable può avere implicazioni molto più grandi. In alcuni casi, la cosa corretta può essere la modifica del metodo di non-const, cioè proprio al fatto che essa sta modificando stato.

Tutto dipende da quanto le questioni const correttezza nel vostro contesto - non volete finire mutable proprio sprinking giro come polvere di fata per rendere il lavoro roba, ma mutable è destinato per l'utilizzo se la parte membro isnt dello stato osservabile dell'oggetto. La vista più severe const correttezza terrebbe che non un singolo bit di stato dell'oggetto può essere modificato (ad esempio, questo potrebbe essere importante se siete istanza è in ROM ...) - in quei casi non volete qualsiasi constness essere perso. In altri casi, si potrebbe avere qualche stato esterno memorizzati da qualche parte ouside dell'oggetto - per esempio, una cache-specific thread che ha anche bisogno di essere considerato al momento di decidere se è appropriato

.

Altri suggerimenti

Questo scenario - un cambiamento di stato interno incapsulato che non incide stato esterno (ad esempio risultati caching) -. È esattamente ciò che la parola chiave è per mutable

const_cast è quasi sempre un segno di fallimento del design. Nel tuo esempio, sia func() non deve essere const, o myMember dovrebbe essere mutable.

Un chiamante di func() si aspetta il suo oggetto non cambiare; ma questo significa "non cambiare in un modo che può notare"; questo è, per non cambiare il suo stato esterno. Se cambiare myMember non cambia lo stato esterno dell'oggetto, questo è ciò che la parola chiave è per mutable; in caso contrario, non dovrebbe essere func() const, perché si sarebbe tradire le vostre garanzie di funzione.

Ricordate che mutable non è un meccanismo per circunvent const correttezza; si tratta di un meccanismo per migliorarlo.

class Class{
int value;
void func()const{
const_cast<Class*>(this)->value=123;
}
};

Come ha scritto Steve Gilham, mutable è la corretta (e breve) risposta alla tua domanda. Voglio solo dare un suggerimento in una direzione diversa. Forse è possibile nella vostra szenario di fare uso di una (o più di uno) interfaccia? Forse si può Grok dal seguente esempio:

class IRestrictedWriter // may change only some members
{
public:
  virtual void func() = 0; 
}

class MyClass : virtual public IRestrictedWriter
{
public:
  virtual void func()
  {
    mValueToBeWrittenFromEverybody = 123; 
  }

  void otherFunctionNotAccessibleViaIRestrictedWriter()
  {
    mOtherValue1 = 123;
    mOtherValue2 = 345;
  }

  ...   
}

Quindi, se si passa a qualche funzione un IRestrictedReader * invece di una const MyClass * può chiamare func e quindi cambiare mValueToBeWrittenFromEverybody mentre mOtherValue1 è una specie di "const".

. Trovo mutable sempre un po 'di hack (ma usarla a volte).

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top