Quelle est la signification de const
dans des déclarations comme celles-ci ? Le site const
m'embrouille.
class foobar
{
public:
operator int () const;
const char* foo() const;
};
Quelle est la signification de const
dans des déclarations comme celles-ci ? Le site const
m'embrouille.
class foobar
{
public:
operator int () const;
const char* foo() const;
};
Lorsque vous ajoutez le const
à une méthode, le this
Le pointeur deviendra const, et vous ne pourrez donc pas modifier le code membre. (A moins que vous n'utilisiez mutable
(nous y reviendrons plus tard).
Le site const
Le mot clé fait partie de la signature des fonctions, ce qui signifie que vous pouvez implémenter deux méthodes similaires, l'une qui est appelée lorsque l'objet est const, et l'autre qui ne l'est pas.
#include <iostream>
class MyClass
{
private:
int counter = 0;
public:
void Foo()
{
std::cout << "Foo" << std::endl;
}
void Foo() const
{
std::cout << "Foo const" << std::endl;
}
};
int main(void)
{
MyClass* cc = new MyClass();
const MyClass* ccc = cc;
cc->Foo();
ccc->Foo();
delete cc;
ccc = null;
return 0;
}
Cela donnera
Foo
Foo const
Dans la méthode non-const, vous pouvez modifier les membres de l'instance, ce que vous ne pouvez pas faire dans la version const. Si vous remplacez la déclaration de méthode de l'exemple ci-dessus par le code ci-dessous, vous obtiendrez des erreurs.
void Foo()
{
counter++; //this works
std::cout << "Foo" << std::endl;
}
void Foo() const
{
counter++; //this will not compile
std::cout << "Foo const" << std::endl;
}
Ce n'est pas tout à fait vrai, car vous pouvez marquer un membre comme "mutable" et une méthode const peut alors le modifier. C'est surtout utilisé pour les compteurs internes et autres. La solution pour cela serait le code ci-dessous.
#include <iostream>
class MyClass
{
private:
mutable int counter;
public:
MyClass() : counter(0) {}
void Foo()
{
counter++;
std::cout << "Foo" << std::endl;
}
void Foo() const
{
counter++;
std::cout << "Foo const" << std::endl;
}
int GetInvocations() const
{
return counter;
}
};
int main(void)
{
MyClass* cc = new MyClass();
const MyClass* ccc = cc;
cc->Foo();
ccc->Foo();
std::cout << "The MyClass instance has been invoked" << ccc->GetInvocations() << " times" << endl;
delete cc;
ccc = NULL;
return 0;
}
ce qui donnerait
Foo
Foo const
The MyClass instance has been invoked 2 times
Le const signifie que la méthode promet de ne modifier aucun membre de la classe. Vous serez en mesure d'exécuter les membres de l'objet qui sont ainsi marqués, même si l'objet lui-même est marqué const
:
const foobar fb;
fb.foo();
serait légal.
Voir Combien et quelles sont les utilisations de "const" en C++ ? pour plus d'informations.
Le qualificatif const signifie que les méthodes peuvent être appelées sur n'importe quelle valeur de foobar. La différence se fait sentir lorsque l'on envisage d'appeler une méthode non const sur un objet const. Imaginez que votre type foobar ait la déclaration de méthode supplémentaire suivante
class foobar {
...
const char* bar();
}
La méthode "bar" est non-const et ne peut être accessible qu'à partir de valeurs non-const.
void func1(const foobar& fb1, foobar& fb2) {
const char* v1 = fb1.bar(); // won't compile
const char* v2 = fb2.bar(); // works
}
L'idée derrière const est de marquer les méthodes qui ne modifieront pas l'état interne de la classe. Il s'agit d'un concept puissant mais qui n'est pas réellement applicable en C++. Il s'agit plus d'une promesse que d'une garantie. Et c'est une promesse qui est souvent et facilement rompue.
foobar& fbNonConst = const_cast<foobar&>(fb1);
Ces constantes signifient que le compilateur se trompe si la méthode 'avec const' modifie les données internes.
class A
{
public:
A():member_()
{
}
int hashGetter() const
{
state_ = 1;
return member_;
}
int goodGetter() const
{
return member_;
}
int getter() const
{
//member_ = 2; // error
return member_;
}
int badGetter()
{
return member_;
}
private:
mutable int state_;
int member_;
};
Le test
int main()
{
const A a1;
a1.badGetter(); // doesn't work
a1.goodGetter(); // works
a1.hashGetter(); // works
A a2;
a2.badGetter(); // works
a2.goodGetter(); // works
a2.hashGetter(); // works
}
Lire ce pour plus d'informations
La réponse de Blair est pertinente.
Notez toutefois qu'il existe un mutable
qui peut être ajouté aux membres de données d'une classe. Tout membre ainsi marqué peut être modifié dans un const
sans violer la méthode const
contrat.
Vous pouvez l'utiliser (par exemple) si vous voulez qu'un objet se souvienne du nombre de fois qu'une méthode particulière est appelée, sans pour autant affecter la constance "logique" de cette méthode.
Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.