Ricerca…


Sintassi

  • const Type myVariable = initial; // Dichiara una variabile const; non può essere cambiato
  • const Type & myReference = myVariable; // Dichiara un riferimento a una variabile const
  • const Type * myPointer = & myVariable; // Dichiara un puntatore-a-const. Il puntatore può cambiare, ma il membro dati sottostante non può essere modificato tramite il puntatore
  • Digita * const myPointer = & myVariable; // Dichiara un puntatore const. Il puntatore non può essere riassegnato per puntare a qualcos'altro, ma il membro dati sottostante può essere modificato
  • const Type * const myPointer = & myVariable; // Dichiara un const pointer-to-const.

Osservazioni

Una variabile contrassegnati come const non può essere modificata 1. Il tentativo di chiamare qualsiasi operazione non const su di esso comporterà un errore del compilatore.

1: Beh, può essere cambiato tramite const_cast , ma non dovresti quasi mai usarlo

Const variabili locali

Dichiarazione e uso.

// 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

Legame di riferimenti e puntatori

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

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

Funzioni membro Const

Le funzioni membro di una classe possono essere dichiarate const , che dice al compilatore e ai futuri lettori che questa funzione non modificherà l'oggetto:

class MyClass
{
private:
    int myInt_;
public:
    int myInt() const { return myInt_; }
    void setMyInt(int myInt) { myInt_ = myInt; }
};

In una funzione membro const , this puntatore è effettivamente un const MyClass * invece di un MyClass * . Ciò significa che non è possibile modificare alcuna variabile membro all'interno della funzione; il compilatore emetterà un avvertimento. Quindi setMyInt non può essere dichiarato const .

Dovresti quasi sempre contrassegnare le funzioni membro come const quando possibile. Solo le funzioni membro const possono essere chiamate su const MyClass .

static metodi static non possono essere dichiarati come const . Questo perché un metodo statico appartiene a una classe e non è chiamato su oggetto; quindi non può mai modificare le variabili interne dell'oggetto. Quindi dichiarare static metodi static come const sarebbe ridondante.

Evitare la duplicazione del codice nei metodi getter const e non-const.

Nei metodi C ++ che differiscono solo dal const qualificatore possono essere sovraccaricati. A volte potrebbe essere necessario disporre di due versioni di getter che restituiscono un riferimento ad un membro.

Lascia che Foo sia una classe, che ha due metodi che eseguono operazioni identiche e restituisce un riferimento a un oggetto di tipo Bar :

class Foo
{
public:
    Bar& GetBar(/* some arguments */)
    {
        /* some calculations */
        return bar;
    }
    
    const Bar& GetBar(/* some arguments */) const
    {
        /* some calculations */
        return bar;
    }

    // ...
};

L'unica differenza tra loro è che un metodo è non-const e restituisce un riferimento non-const (che può essere utilizzato per modificare l'oggetto) e il secondo è const e restituisce const riferimento.

Per evitare la duplicazione del codice, c'è la tentazione di chiamare un metodo da un altro. Tuttavia, non possiamo chiamare il metodo non-const da quello const. Ma possiamo chiamare il metodo const da quello non const. Ciò richiederà di usare 'const_cast' per rimuovere il qualificatore const.

La soluzione è:

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

Nel codice qui sopra, chiamiamo la versione const di GetBar dalla GetBar non-const GetBar in tipo const: const_cast<const Foo*>(this) . Siccome chiamiamo il metodo const da non-const, l'oggetto stesso è non-const, e il cast via è const.

Esaminare il seguente esempio più completo:

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


Modified text is an extract of the original Stack Overflow Documentation
Autorizzato sotto CC BY-SA 3.0
Non affiliato con Stack Overflow