Question

J'ai un membre de la classe myMember qui est myType pointeur. Je veux attribuer à ce membre dans une fonction qui est déclarée const. Je fais comme suit:

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

Faire cela fonctionne très bien dans VC ++, mais GCC donne une erreur avec le message « lvalue requis comme opérande gauche d'affectation ».

Faire le membre mutable me permettent de supprimer simplement le const_cast et affecter la valeur. Cependant, je ne suis pas tout à fait sûr que cela vient avec d'autres effets secondaires.

Puis-je attribuer mon membre sans avoir à faire le membre mutable? Comment? Y a-t-il des effets secondaires à faire des membres mutable?

Était-ce utile?

La solution

Le code ne fonctionnera pas réellement dans VC ++ - vous n'êtes pas mise à jour de la valeur (ou du moins il ne devrait pas), d'où l'avertissement du CCG. code correct est

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

ou [de l'autre réponse, merci: P]:

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

Rendre mutable signifie effectivement que vous obtenez const_casts implicites dans les fonctions membres de const, qui est généralement ce que vous devriez orienter vers quand vous vous trouvez faire des charges de const_casts sur this. Il n'y a pas « effets secondaires à l'utilisation mutable » autre que cela.

Comme vous pouvez le voir dans les débats véhéments encerclant cette question, l'utilisation bon gré mal gré mutable et beaucoup de const_casts peut certainement être des symptômes de mauvaises odeurs dans votre code. D'un point de vue conceptuel, coulée ou à l'aide constness loin mutable peut avoir des conséquences beaucoup plus importantes. Dans certains cas, la bonne chose à faire peut-être changer la méthode non-const, à savoir posséder au fait qu'il modifie l'état.

Tout dépend de combien les questions const-exactitude dans votre contexte - vous ne voulez pas finir par mutable juste sprinking autour comme la poussière de Pixie pour faire le travail de choses, mais mutable est destiné à un usage si la partie ISNT membre de l'état observable de l'objet. La vue la plus stricte de const-exactitude détiendrait que pas un seul bit de l'état de l'objet peut être modifié (par exemple, cela pourrait être critique si vous êtes par exemple est en ROM ...) - dans ces cas, vous ne voulez pas tout constness être perdu. Dans d'autres cas, vous pourriez avoir un état externe stocké quelque part ouside de l'objet - par exemple, un cache spécifique thread qui doit également être pris en considération au moment de décider si elle est appropriée

.

Autres conseils

Ce scénario - un changement d'état interne encapsulé qui n'a pas d'impact état externe (par exemple des résultats de la mise en cache) -. Est exactement ce que le mot-clé mutable est pour

const_cast est presque toujours un signe d'échec de la conception. Dans votre exemple, que ce soit func() ne doit pas être const ou myMember doit être mutable.

Un appelant de func() s'attendra à son objet de ne pas changer; mais cela signifie « ne pas changer d'une manière qu'elle peut remarquer »; c'est de ne pas changer son état externe. Si le changement myMember ne change pas l'objet état extérieur, c'est-ce que le mot-clé mutable est pour; sinon, func() ne doit pas être const, parce que vous trahirais vos garanties de fonction.

Rappelez-vous que mutable n'est pas un mécanisme pour circunvent const-exactitude; il est un mécanisme pour l'améliorer.

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

Comme Steve Gilham a écrit, mutable est la bonne réponse (et court) à votre question. Je veux juste vous donner un indice dans une autre direction. Peut-être qu'il est possible dans votre Szenario d'utiliser une interface (ou plusieurs)? Peut-être vous pouvez assimilez à partir de l'exemple suivant:

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;
  }

  ...   
}

Alors, si vous passez à une fonction d'un IRestrictedReader * au lieu d'un const MyClass * il peut appeler func et donc changer mValueToBeWrittenFromEverybody alors mOtherValue1 est une sorte de « const ».

. Je trouve mutable toujours un peu un hack (mais parfois l'utiliser).

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top