C++
mot clé const
Recherche…
Syntaxe
- const Type myVariable = initial; // déclare une variable const; ne peut pas être changé
- const Type & myReference = myVariable; // déclare une référence à une variable const
- const Type * myPointer = & myVariable; // Déclare un pointeur sur const. Le pointeur peut changer, mais le membre de données sous-jacent ne peut pas être modifié via le pointeur
- Tapez * const myPointer = & myVariable; // Déclare un pointeur const. Le pointeur ne peut pas être réaffecté pour pointer sur autre chose, mais le membre de données sous-jacent peut être modifié
- const Type * const myPointer = & myVariable; // déclare un const pointeur sur const.
Remarques
Une variable marquée comme const
ne peut pas être changé 1. Si vous tentez d'appeler des opérations autres que des const sur cela entraînera une erreur de compilation.
1: Eh bien, il peut être changé par const_cast
, mais vous ne devriez presque jamais l'utiliser
Variables locales const
Déclaration et usage
// a is const int, so it can't be changed
const int a = 15;
a = 12; // Error: can't assign new value to const variable
a += 1; // Error: can't assign new value to const variable
Reliure de références et de pointeurs
int &b = a; // Error: can't bind non-const reference to const variable
const int &c = a; // OK; c is a const reference
int *d = &a; // Error: can't bind pointer-to-non-const to const variable
const int *e = &a // OK; e is a pointer-to-const
int f = 0;
e = &f; // OK; e is a non-const pointer-to-const,
// which means that it can be rebound to new int* or const int*
*e = 1 // Error: e is a pointer-to-const which means that
// the value it points to can't be changed through dereferencing e
int *g = &f;
*g = 1; // OK; this value still can be changed through dereferencing
// a pointer-not-to-const
Pointeurs Const
int a = 0, b = 2;
const int* pA = &a; // pointer-to-const. `a` can't be changed through this
int* const pB = &a; // const pointer. `a` can be changed, but this pointer can't.
const int* const pC = &a; // const pointer-to-const.
//Error: Cannot assign to a const reference
*pA = b;
pA = &b;
*pB = b;
//Error: Cannot assign to const pointer
pB = &b;
//Error: Cannot assign to a const reference
*pC = b;
//Error: Cannot assign to const pointer
pC = &b;
Fonctions de membre Const
Les fonctions membres d'une classe peuvent être déclarées const
, ce qui indique au compilateur et aux futurs lecteurs que cette fonction ne modifiera pas l'objet:
class MyClass
{
private:
int myInt_;
public:
int myInt() const { return myInt_; }
void setMyInt(int myInt) { myInt_ = myInt; }
};
Dans une fonction membre const
, le pointeur this
est en fait un const MyClass *
au lieu d'un MyClass *
. Cela signifie que vous ne pouvez modifier aucune variable membre dans la fonction; le compilateur émettra un avertissement. Donc, setMyInt
n'a pas pu être déclaré const
.
Vous devriez presque toujours marquer les fonctions des membres comme const
lorsque cela est possible. Seules les fonctions de membre const
peuvent être appelées sur un const MyClass
.
static
méthodes static
ne peuvent pas être déclarées comme const
. En effet, une méthode statique appartient à une classe et n’est pas appelée sur l’objet; par conséquent, il ne peut jamais modifier les variables internes de l'objet. Donc, déclarer static
méthodes static
comme const
serait redondant.
Éviter la duplication du code dans les méthodes get const et non const.
En C ++, les méthodes qui ne diffèrent que par un qualificateur const
peuvent être surchargées. Parfois, deux versions de getter peuvent être nécessaires pour renvoyer une référence à un membre.
Soit Foo
une classe, qui a deux méthodes qui effectuent des opérations identiques et renvoie une référence à un objet de type Bar
:
class Foo
{
public:
Bar& GetBar(/* some arguments */)
{
/* some calculations */
return bar;
}
const Bar& GetBar(/* some arguments */) const
{
/* some calculations */
return bar;
}
// ...
};
La seule différence entre eux est qu'une méthode est non-const et renvoie une référence non-const (qui peut être utilisée pour modifier un objet) et la seconde est const et renvoie une référence const.
Pour éviter la duplication de code, il est tentant d'appeler une méthode d'une autre. Cependant, nous ne pouvons pas appeler la méthode non-const du const. Mais on peut appeler la méthode const de non-const. Cela nécessitera d'utiliser 'const_cast' pour supprimer le qualificatif const.
La solution est la suivante:
struct Foo
{
Bar& GetBar(/*arguments*/)
{
return const_cast<Bar&>(const_cast<const Foo*>(this)->GetBar(/*arguments*/));
}
const Bar& GetBar(/*arguments*/) const
{
/* some calculations */
return foo;
}
};
Dans le code ci-dessus, nous appelons la version const de GetBar
partir du non-const GetBar
en le GetBar
en const: const_cast<const Foo*>(this)
. Puisque nous appelons la méthode const de non-const, l'objet lui-même est non-const, et le rejet de const est autorisé.
Examinez l'exemple plus complet suivant:
#include <iostream>
class Student
{
public:
char& GetScore(bool midterm)
{
return const_cast<char&>(const_cast<const Student*>(this)->GetScore(midterm));
}
const char& GetScore(bool midterm) const
{
if (midterm)
{
return midtermScore;
}
else
{
return finalScore;
}
}
private:
char midtermScore;
char finalScore;
};
int main()
{
// non-const object
Student a;
// We can assign to the reference. Non-const version of GetScore is called
a.GetScore(true) = 'B';
a.GetScore(false) = 'A';
// const object
const Student b(a);
// We still can call GetScore method of const object,
// because we have overloaded const version of GetScore
std::cout << b.GetScore(true) << b.GetScore(false) << '\n';
}