J'ai un membre de la classe mymember em> c'est un pointeur mytype em>. Je veux affecter ce membre dans une fonction déclarée Const. Je fais comme suit: void func() const
{
...
const_cast<myType*>(myMember) = new myType();
...
}
5 Réponses :
Ce scénario - Un changement d'état interne encapsulé qui n'a pas d'impact sur l'état externe (par exemple les résultats de la mise en cache) - est exactement ce que le mot clé mutable code> est destiné. P>
Mutable n'est pas bon si vous voulez obtenir un accès en écriture à un membre dans une seule méthode constante.
L'état observable à l'extérieur de l'objet ne doit pas changer lors de l'écriture sur un objet mutable. Faire un membre mutable juste pour contourner une erreur dans une fonction Const n'est pas légitime si le changement est visible de l'extérieur et peut conduire à un comportement non défini. Les utilisations légitimes d'un mutable incluent la mise en cache, où par exemple, le même appel reprend deux fois le même résultat, mais plus vite.
class Class{ int value; void func()const{ const_cast<Class*>(this)->value=123; } };
Vous avez besoin d'un objet moulé au lieu d'un membre.
Merci. Je vais par le premier code de Ruben depuis qu'il a l'air plus propre. Si je pouvais, je marquerais comme "réponse".
Le code ne fonctionne pas réellement en VC ++ - vous ne mettez pas à jour la valeur (ou au moins cela ne devrait pas), d'où l'avertissement de GCC. Le code correct est ou [à partir d'une autre réponse, merci: p]: p> la rendre mutable signifie efficacement "code > const_cast code> S dans Comme vous pouvez le constater sur les débats véhément à la suite de cette question, une utilisation willy-nilly de Tout dépend de la quantité de constance importante dans votre contexte - vous ne voulez pas finir simplement par Sprinking Const code> Fonctions membres, qui est généralement ce que vous devriez vous diriger vers lorsque vous vous trouvez en train de faire des charges de
const_cast code> S sur
Ceci < / code>. Il n'y a pas de "effets secondaires à l'utilisation mutable" autre que cela. P>
mutable code> et beaucoup de
const_cast code> s peut certainement être des symptômes de mauvais sent votre code. D'un point de vue conceptuel, la consensions de la constance ou l'utilisation de
mutable code> peut avoir des implications beaucoup plus importantes. Dans certains cas, la bonne chose à faire peut être de modifier la méthode à la non-const, c'est-à-dire que celle-ci est de modifier l'état. P>
mutable code> autour de la poussière de Pixie pour faire fonctionner des trucs, mais
mutable code> est destiné à être utilisé si le membre n'a pas une partie de l'observable état de l'objet. La vue la plus stricte de la const-Cidressness conserve que non un seul bit de l'état de l'objet ne peut être modifié (par exemple, cela pourrait être essentiel si votre instance est en rom ...) - Dans ces cas, vous ne voulez pas de Conscience être perdu. Dans d'autres cas, vous pourriez avoir un état externe stocké quelque part d'ouside de l'objet - par exemple, un cache spécifique au fil qui doit également être pris en compte lors de la décision si elle est appropriée. P> P>
Je pense que cela fonctionne que c'est peut-être la pire solution. Cela cache complètement ce qui se passe (changeant un état interne d'une instance immuable) dans une constance dans la fonction membre. "mutable" serait plus claire (ou utilise des interfaces).
La création de la constance conduit à un comportement indéfini. À utiliser à vos risques et périls. Une meilleure solution serait de faire la méthode non Const.
@Lokiastari Non, Casting Away Const CODE> NESS n'invoque pas UB - à moins que l'objet référé sous-jacent n'a été déclaré à l'origine
const code>, un faux pas à l'IMO rend le programmeur méritant l'UB. Pour le reste, en référence aux objets qui n'étaient pas
Const code> -qualifiés à leur déclaration, la création de
const code> ness est parfaitement i> bien défini. Ici: Stackoverflow.com/a/3485333/2757035
@underscore_d Nope. Je n'ai jamais dit que c'était UB. J'ai dit qu'il conduit à UB. Si vous éloignez la Constance dans une méthode constante, vous risquez de causer une UB. Si vous ajoutez la Centaness dans une méthode sans coût, rien de mal ne se produira. Je me tiens à mon énoncé d'origine. Voir aussi: Stackoverflow.com/q/4042626/14065 Modification de tout objet où le const a été renvoyé " May " b> cause UB. Ce n'est peut-être pas qu'une implémentation conforme peut (ce qui permet certaines optimisations). Modification d'un objet qui était en réalité est définitivement ub.
@Lokiastari Votre utilisation de "mène à" est invisible - vous vouliez dire "rendre le programmeur susceptible de faire quelque chose de Daft", mais la plupart des gens vont lire cela comme "causes directement". Quoi qu'il en soit, nos deux liens proposent des citations suggérant que le résultat est défini, tant que l'objet d'origine n'était pas déclaré const code>. La citation d'ouverture de votre lien semble contredire cela - mais liens vers le même exemple que je cite i>. Je pense que c'est un autre morceau de formulation médiocre par la norme, mais, comme cela se passe pour citer un exemple défini d'un
const_cast code> ED PTR modifiant un objet non code> const code> objet, doit Continuez à parier sur ma 1ère interprétation.
@underscore_d je suis en désaccord. Vous dites essentiellement que, dans certaines circonstances, la consensions est bien. Bien que techniquement correct, le point soit obtus (quand il y a une écriture impliquée) et donc je ne suis pas d'accord et que le code est fondamentalement cassé b>. À l'intérieur d'une méthode, il n'ya aucun moyen de dire si l'objet d'origine était constitué ou non et que vous jouez donc essentiellement de la roulette russe. Code qui est fragile et dépend des curcumstances pour être soit UB ou non est cassé. Alors oui, je ne le dis pas explicitement, j'insère très fortement que cela va faire sauter dans votre visage.
Le cependant que si j'ai un objet Const et appelez une méthode de const que mon code présentera UB ne devrait pas arriver. Je n'ai probablement pas écrit la méthode en question (j'utilise beaucoup de code d'autres personnes). Donc, avoir l'auteur crée des cours qui peuvent exploser mon code lorsque je l'appelle correctement est un comportement brisé. Ainsi, ma déclaration originale est debout.
Un appelant de N'oubliez pas que const_cast code> est presque toujours un signe de défaillance de la conception. Dans votre exemple,
func () code> ne doit pas être
const code> ou
MyMember code> doit être
mutable p >
Func () code> s'attendre à ce que son objet ne change pas; Mais cela signifie "ne pas changer d'une manière qu'elle peut remarquer"; C'est non plus de changer d'état externe. Si vous modifiez
MyMember code> ne modifie pas l'état externe de l'objet, c'est ce que le mot clé
mutable code> est pour; Sinon,
func () code> ne doit pas être
const code>, car vous trahissez vos garanties de fonction. P>
mutable code> n'est pas un mécanisme de Circunvent Const-Constance; C'est un mécanisme pour l'améliorer. P>
^ Oui, et parfois, l'échec est dans une bibliothèque que vous utilisez! J'utilise un qui prend un pointeur à non- const code> mais (et je vérifie cela régulièrement :) ne mutait pas l'objet. Sécuriser dans cette connaissance, je peux donc passer tout
obj const & code> (y compris temporaire) à ladite bibliothèque, je l'enveloppe dans une fonction qui fait un
const_cast
obj code> et me permet de faire de meilleures choses avec la bibliothèque ... au moins jusqu'à ce que l'auteur décide d'utiliser C ++ plus que c [soupir]
@underscore_d c'est l'une des utilisations légitimes de const_cast code>: Traiter avec imperfecté C ++. Si j'avais un cent pour chaque ponter-to-non constitue qui devrait être un pointeur à Const dans le monde ...
@Gorpik à coup sûr. Comme un de côté, je me demande combien de ces problèmes sont causés par des personnes qui ne respectent tout simplement pas const code> -Correcness - et combien par des personnes essayant de i> mais pas d'utilisation de droite-to -Le ordre de déclaration limite ;-)
As Steve Gilham écrit, mutable code> est la réponse correcte (et courte) à votre question. Je veux juste vous donner un indice dans une direction différente.
Peut-être que c'est possible dans votre Szenario d'utiliser une interface (ou plus d'une)?
Peut-être pouvez-vous le greffer à 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;
}
...
}