156 votes

Signification du dernier "const" dans une déclaration de méthode C++ ?

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;
};

193voto

Mats Fredriksson Points 7136

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

99voto

Blair Conrad Points 56195

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.

17voto

JaredPar Points 333733

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);

8voto

Mykola Golubyev Points 21210

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

7voto

Alnitak Points 143355

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.com

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.

Powered by:

X