Modification de soi dans la méthode const via un pointeur non const vers soi
Question
Dans l'exemple suivant const
l'objet peut se modifier via const
méthode, car dans cette méthode, il accède à lui-même via non-const
aiguille.(même programme sur ideone)
#include <iostream>
struct Object;
Object * g_pObject;
struct Object
{
Object():m_a(0){}
void ModifySelfViaConstMethod() const
{
g_pObject->m_a = 37;
}
int m_a;
};
int main()
{
Object o;
g_pObject = &o;
const Object & co = o;
std::cout << co.m_a << "\n";
co.ModifySelfViaConstMethod();
std::cout << co.m_a << "\n";
return 0;
}
Je ne suis pas très doué pour lire le standard C++, alors je demande ici :
Que dit la norme à ce sujet ?
un)const
la méthode ne vous garantit pas que votre objet reste inchangé lorsque vous faites des choses comme celle-ci
b) Est-ce que c'est bien défini ça et il faut compiler
c) autre ?
La solution
Que dit la norme à ce sujet ?
Il dit (paraphrasant) que this
a du type const Object *
, de sorte que vous ne puissiez pas modifier directement les membres ou appeler des fonctions membres non const via this
.Cela ne dit rien sur ce que vous pouvez faire avec les variables globales auxquelles la fonction pourrait avoir accès ;il contrôle uniquement l'accès direct à l'objet sur lequel la fonction est appelée.
const
la méthode ne vous garantit pas que votre objet reste inchangé lorsque vous faites des choses comme celle-ci
Non, ce n'est pas le cas.Il indique l'intention que la fonction ne modifiera pas l'objet et offre une certaine protection contre la rupture accidentelle de cette intention.Cela n'empêche pas un programmeur suffisamment dérangé d'utiliser const_cast
, ou (comme ici) un couplage incontrôlé via des variables globales pour rompre la promesse.
Est-ce que c'est bien défini et il faut compiler
Oui. o
n'est pas lui-même constant, donc rien ne vous empêche de prendre un pointeur non const ou une référence à celui-ci.Le const
sur la fonction membre restreint uniquement l'accès à l'objet via this
, pas vers des objets arbitraires via d'autres pointeurs.
Autres conseils
Lorsque vous déclarez un const
fonction, c'est "pour votre bien".
En d'autres termes, vous le déclarez const
car selon votre conception initiale, il n'est censé modifier aucun objet avec lequel il sera invoqué pendant l'exécution.
Si, à un moment ultérieur de l'implémentation de cette fonction, vous finissez par modifier l'objet, le compilateur vous "criera dessus", vous disant que c'est faux.
Bien entendu, le compilateur sera capable d'identifier une telle tentative, uniquement lorsqu'elle sera appliquée sur this
.
Dans l'exemple donné, le compilateur ne peut pas identifier le problème car il nécessite une comparaison entre this
et g_pObject
, et une telle comparaison ne peut avoir lieu que pendant l'exécution.
Lorsqu'une méthode est déclarée comme const
, le compilateur s'assure que l'instance pointée par le this
le pointeur n’est pas modifié.Si vous essayez de modifier le this
par exemple, le compilateur échoue.Cependant, le compilateur n'a aucun moyen de savoir que g_pObject
et this
pointent en fait vers la même instance.Cela nécessite une comparaison à l'exécution, et aucun compilateur ne perdra de temps à effectuer des comparaisons à l'exécution de chaque pointeur utilisé dans un const
méthode au cas où ils pourrait correspond à this
aiguille.Donc, si vous envisagez de modifier un Object
via un pointeur externe, vous allez devoir faire votre propre vérification, par exemple :
void ModifySelfViaConstMethod() const
{
if (g_pObject != this)
g_pObject->m_a = 37;
}
La constance en C++ est un instrument de sécurité, pas de sécurité.
Le code dans lequel la constance est honorée fonctionnera très probablement comme prévu, et toutes les tentatives involontaires de rejet de la constance seront alertées par le compilateur.
Dans les cas où "je sais ce que je fais", on peut trouver toute une variété d'outils, depuis const_cast
opérateur et mutable
mot-clé du casting banal de style C.