Les méthodes C ++ permettent à un qualificateur const
d’indiquer que l’object n’est pas modifié par la méthode. Mais qu’est ce que ça veut dire? Par exemple. si les variables d’instance sont des pointeurs, cela signifie-t-il que les pointeurs ne sont pas modifiés ou que la mémoire sur laquelle elles pointent n’est pas modifiée?
Concrètement, voici un exemple minimal de classe
class myclass { int * data; myclass() { data = new int[10]; } ~myclass() { delete [] data; } void set(const int index) const { data[index] = 1; } };
La méthode set
correctement est-elle qualifiée de const
? Cela ne change pas les data
variable membre, mais cela change certainement le contenu du tableau.
Plus simplement, cela signifie que le type de this
est const T *
intérieur de fonctions membres const, où T
est votre classe, alors que dans les fonctions non qualifiées, il s’agit de T *
.
Votre set
méthodes ne modifie pas les data
, il peut donc être qualifié de const. En d’autres termes, myclass::data
est accessible en tant que this->data
et est de type int * const
.
Qu’est-ce qu’une méthode ‘const’ peut changer?
Sans exclure explicitement constness, une méthode const
peut changer:
mutable
, et const
, que ces données soient ou non accessibles:
Pour les membres de type class
/ struct
/ union
, il s’appuie sur la constance de leurs fonctions membre pour déterminer les opérations à autoriser. (Cela peut également changer les variables locales non constantes et les parameters par valeur, mais je sais que ce n’est pas ce qui vous intéresse).
Il peut appeler d’autres méthodes const
qui auront ces mêmes capacités et ressortingctions.
Par exemple. si les variables d’instance sont des pointeurs, cela signifie-t-il que les pointeurs ne sont pas modifiés ou que la mémoire sur laquelle elles pointent n’est pas modifiée?
Cela signifie que les pointeurs ne peuvent pas être modifiés (facilement / accidentellement). Cela ne signifie pas que la mémoire pointée ne peut pas être changée.
Ce que vous avez découvert, c’est l’inconvénient logique d’une fonction const
qui modifie des données pointées ou référencées appartenant conceptuellement à l’object. Comme vous l’avez constaté, le compilateur n’applique pas l’exactitude de const
que vous souhaitez peut-être ou attendez ici. C’est un peu dangereux, mais cela signifie que la constance n’a pas besoin d’être explicitement supprimée pour les pointeurs / références à d’autres objects qui peuvent être modifiés en tant qu’effet secondaire de la fonction const
. Par exemple, un object de journalisation. (En règle générale, de tels objects ne sont pas logiquement “possédés” par l’object dont la fonction const
est utilisée.) Le point clé est que le compilateur ne peut pas distinguer de manière fiable le type de propriété logique qu’un object a sur les données pointées. il faut deviner d’une manière ou d’une autre et permettre au programmeur de remplacer ou de ne pas être protégé par const
-ness. C ++ renonce à la protection.
Intéressant, j’ai entendu dire que le langage D de Walter Bright inversait cette valeur par défaut, faisant de const
-donnée pointée par défaut dans les fonctions const
. Cela me semble plus sûr, mais il est difficile d’imaginer combien de fois on finira par avoir besoin de rejeter explicitement la constance pour autoriser les effets secondaires recherchés, et si cela donnerait une sensation satisfaisante de précision ou une verbosité ennuyeuse.
Il y a deux aspects à cette question:
const
pour le compilateur? const
s’applique-t-il lorsqu’il ne peut pas être validé par le compilateur? Le premier est plutôt simple. Le compilateur valide qu’aucun membre de données n’est modifié (à moins qu’ils ne soient qualifiés de mutable
). Il le valide de manière récursive: pour tous les types définis par l’utilisateur, il vérifie qu’aucune méthode non const n’est invoquée. Pour les types intégrés, il valide qu’ils ne sont pas affectés.
La transformation des pointeurs est T*
à T*const
(pointeur const), et non pas const T*
(pointeur à const). Cela signifie que le compilateur ne valide pas que l’object pointé n’est pas modifié. Cela mène évidemment à la question 2.
Comment const
s’applique-t-il lorsqu’il n’est pas validé par le compilateur? Cela signifie tout ce que cela devrait signifier pour votre application. Ceci est généralement appelé logique. Quand utiliser const
par rapport à la constance logique est sujet à discussion .
const
gros, const
empêche de changer les valeurs des membres de l’instance de la classe dans la fonction. Ceci est utile pour une interface plus claire, mais pose des ressortingctions lors de l’utilisation de l’inheritance par exemple. C’est parfois un peu trompeur (ou beaucoup en fait), comme dans l’exemple que vous avez posté.
const
serait le plus approprié pour les fonctions Get
, où il est évident que l’appelant lit une valeur et n’a pas l’intention de changer l’état de l’object. Dans ce cas, vous voudrez peut-être aussi limiter les implémentations héritées à la const
, afin d’éviter toute confusion et tout bogue caché lors de l’utilisation du polymorphism.
Par exemple
class A{ int i; public: virtual int GetI() {return i;}; } class B : public A{ public: int GetI() { i = i*2; return i;}; // undesirable }
changer de A à:
virtual int GetI() const {return i;};
résout le problème.
const lorsqu’il est appliqué à une méthode signifie:
Cela signifie que l’ state
de l’object ne sera pas modifié par la méthode.
Cela signifie que tous les membres qui font partie de l’état des objects ne peuvent pas être modifiés, et aucune fonction qui n’est pas également const ne peut être appelée.
En ce qui concerne les pointeurs. Cela signifie que le pointeur (s’il fait partie de l’état) ne peut pas être modifié. Mais l’object pointé par le pointeur fait partie d’un autre object, ce qui signifie que vous pouvez appeler des méthodes sans coût sur cet object (car il ne fait pas partie de l’état de cet object).