cnr - c++ gestione memoria




Significato di 'const' ultimo in una dichiarazione di funzione di una classe? (5)

Il const significa che il metodo promette di non alterare alcun membro della classe. Sarai in grado di eseguire i membri dell'oggetto che sono così marcati, anche se l'oggetto stesso è stato marcato const :

const foobar fb;
fb.foo();

sarebbe legale.

Vedi Quanti e quali sono gli usi di "const" in C ++? per maggiori informazioni.

Qual è il significato di const in dichiarazioni come queste? Il const mi confonde.

class foobar
{
  public:
     operator int () const;
     const char* foo() const;
};

Il qualificatore const indica che i metodi possono essere richiamati su qualsiasi valore di foobar . La differenza arriva quando si considera di chiamare un metodo non-const su un oggetto const. Considera se il tuo tipo di foobar aveva la seguente dichiarazione di metodo aggiuntiva:

class foobar {
  ...
  const char* bar();
}

La bar() metodi bar() è non-const e può essere raggiunta solo da valori non const.

void func1(const foobar& fb1, foobar& fb2) {
  const char* v1 = fb1.bar();  // won't compile
  const char* v2 = fb2.bar();  // works
}

L'idea alla base di const è di marcare metodi che non alterino lo stato interno della classe. Questo è un concetto potente ma non è effettivamente applicabile in C ++. È più una promessa che una garanzia. E uno che è spesso rotto e facilmente rotto.

foobar& fbNonConst = const_cast<foobar&>(fb1);

Quando si aggiunge la parola chiave const a un metodo, this puntatore diventerà essenzialmente un puntatore all'oggetto const e non sarà quindi possibile modificare alcun dato membro. (A meno che non si usi la funzione mutable , ne mutable più avanti).

La parola chiave const fa parte della firma delle funzioni, il che significa che è possibile implementare due metodi simili, uno che viene chiamato quando l'oggetto è const e uno che non lo è.

#include <iostream>

class MyClass
{
private:
    int counter;
public:
    void Foo()
    { 
        std::cout << "Foo" << std::endl;    
    }

    void Foo() const
    {
        std::cout << "Foo const" << std::endl;
    }

};

int main()
{
    MyClass cc;
    const MyClass& ccc = cc;
    cc.Foo();
    ccc.Foo();
}

Questo uscirà

Foo
Foo const

Nel metodo non const puoi cambiare i membri dell'istanza, cosa che non puoi fare nella versione const . Se si modifica la dichiarazione del metodo nell'esempio precedente nel codice riportato di seguito, si otterranno alcuni errori.

    void Foo()
    {
        counter++; //this works
        std::cout << "Foo" << std::endl;    
    }

    void Foo() const
    {
        counter++; //this will not compile
        std::cout << "Foo const" << std::endl;
    }

Questo non è completamente vero, perché è possibile contrassegnare un membro come modificabile e un metodo const può quindi modificarlo. È usato principalmente per contatori interni e cose del genere. La soluzione per questo sarebbe il codice qui sotto.

#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;
    const MyClass& ccc = cc;
    cc.Foo();
    ccc.Foo();
    std::cout << "The MyClass instance has been invoked " << ccc.GetInvocations() << " times" << endl;
}

che produrrebbe

Foo
Foo const
The MyClass instance has been invoked 2 times

Questi const indicano che il compilatore eseguirà Error se il metodo 'with const' modifica i dati interni.

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

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

Leggi this per ulteriori informazioni


Significato di una funzione membro Const in C ++ Common Knowledge: Essential Intermediate Programming fornisce una spiegazione chiara:

Il tipo di questo puntatore in una funzione membro non const di una classe X è X * const. Cioè, è un puntatore costante a una X non costante (vedi Puntatori e Puntatori a Cost [7, 21]). Poiché l'oggetto a cui questo si riferisce non è const, può essere modificato. Il tipo di questo in una funzione membro const di una classe X è const X * const. Cioè, è un puntatore costante a una costante X. Poiché l'oggetto a cui questo si riferisce è const, non può essere modificato. Questa è la differenza tra le funzioni membro const e non-const.

Quindi nel tuo codice:

class foobar
{
  public:
     operator int () const;
     const char* foo() const;
};

Puoi pensare in questo modo:

class foobar
{
  public:
     operator int (const foobar * const this) const;
     const char* foo(const foobar * const this) const;
};




c++-faq