Comment la qualification de const sur les variables diffère-t-elle en C et C ++?
from: Est – ce que “const” signifie seulement en lecture seule ou quelque chose de plus?
“Ce qui a motivé cette question, c’est cette réponse: https://stackoverflow.com/questions/4024318#4024417 où il déclare que” simplement “signifie en lecture seule dans le langage C. C ++. Que veut-il dire? ”
const
en C ne peut pas être utilisé pour construire des expressions constantes.
Par exemple :
#include int main() { int i = 2; const int C = 2; switch(i) { case C : printf("Hello") ; break; default : printf("World"); } }
ne fonctionne pas en C car l’étiquette de cas ne se réduit pas à une constante entière.
const
signifie que vous promettez de ne pas muter la variable. Cela pourrait encore être changé.
class A { public: A(const int& a); int getValue() const; void setValue(int b); private: const int& a; }; A::A(a) : a(a) {} int A::getValue() const { return a; } void A::setValue(int b) { a = b; // error } int main() { int my_a = 0; A a(my_a); std::cout << a.getValue() << std::endl; // prints 0 my_a = 42; std::cout << a.getValue() << std::endl; // prints 42 }
Aucune méthode A::*
peut changer a
, mais le main
peut. Cela est identique entre C et C ++.
Ce que C ++ a, ce sont deux manières (limitées) de contourner const
, qui sont censées décourager les programmeurs de rejeter const
manière inappropriée.
Prenez un cours comme celui-ci.
class A { public: A(); int getValue(); private: static int expensiveComputation(); int cachedComputation; }; A::A() : cachedComputation(0) {} A::getValue() { if (cachedComputation == 0) cachedComputation = expensiveComputation(); return cachedComputation; }
cachedComputation
signifie implicitement cachedComputation
this->cachedComputation
. Garde ça en tête.
int main() { A a1; const A a2; std::cout << a1.getValue() << std::endl; std::cout << a2.getValue() << std::endl; // error }
a2.getValue()
est illégale, car une méthode non const
est appelée sur un const A a2
. On pourrait rejeter la const
-ness…
std::cout << ((A&)a2).getValue() << std::endl; // C-style cast std::cout << const_cast(a2).getValue() << std::endl; // C++-style cast
La seconde est préférable, car le compilateur vérifiera que seule la const
-ness est exprimée, rien d’autre. Cependant, ce n'est toujours pas idéal. Au lieu de cela, une nouvelle méthode devrait être ajoutée à la classe.
class A { public: int getValue() const; }; A::getValue() const { if (cachedComputation == 0) cachedComputation = expensiveComputation(); // error return cachedComputation; }
Maintenant, il existe une méthode const
, donc a2.getValue()
va bien. Cependant, le dernier const
fin signifie que la méthode reçoit un const A *this
pointeur, et non un A *this
pointeur comme d'habitude, ce qui fait de this->cachedComputation
un const int &
ne pouvant pas être muté.
const_cast
pourrait être appliqué à l'intérieur de la méthode, mais il serait préférable de changer la déclaration de ce membre.
class A { private: mutable int cachedComputation; };
Maintenant, même avec un const A *this
, this->cachedComputation
peut être muté sans transtypage.