Buscar..


Sintaxis

  • const Tipo myVariable = initial; // Declara una variable const; no puede ser cambiado
  • Tipo const y myReference = myVariable; // Declara una referencia a una variable const.
  • Tipo const * myPointer = & myVariable; // Declara un puntero a const. El puntero puede cambiar, pero el miembro de datos subyacente no se puede cambiar a través del puntero
  • Escriba * const myPointer = & myVariable; // Declara un puntero const. El puntero no se puede reasignar para apuntar a otra cosa, pero el miembro de datos subyacente se puede cambiar
  • Tipo const * const myPointer = & myVariable; // Declara una constante puntero a const.

Observaciones

Una variable marcada como const no puede ser cambiada 1. Intentar llamar a cualquier operación que no sea constante en él resultará en un error del compilador.

1: Bueno, se puede cambiar a través de const_cast , pero casi nunca deberías usar eso

Variables locales const

Declaración y 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

Encuadernación de referencias y punteros.

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

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

Funciones de miembro const

Las funciones de miembro de una clase se pueden declarar const , que le dice al compilador y a los futuros lectores que esta función no modificará el objeto:

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

En una función miembro de const , this puntero es efectivamente una const MyClass * lugar de una MyClass * . Esto significa que no puede cambiar ninguna variable miembro dentro de la función; El compilador emitirá una advertencia. Entonces setMyInt no pudo ser declarado const .

Casi siempre debe marcar las funciones miembro como const cuando sea posible. Sólo se pueden llamar a las funciones miembro const en una const MyClass .

static métodos static no pueden ser declarados como const . Esto se debe a que un método estático pertenece a una clase y no se llama en un objeto; por lo tanto, nunca puede modificar las variables internas del objeto. Así que declarar métodos static como const sería redundante.

Evitar la duplicación de código en los métodos const y non-const getter.

En C ++, los métodos que difieren solo por el calificador const pueden sobrecargarse. A veces es posible que se necesiten dos versiones de getter que devuelvan una referencia a algún miembro.

Deje que Foo sea ​​una clase, que tiene dos métodos que realizan operaciones idénticas y devuelve una referencia a un objeto de tipo Bar :

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

    // ...
};

La única diferencia entre ellos es que un método es non-const y devuelve una referencia non-const (que se puede usar para modificar un objeto) y el segundo es const y devuelve una referencia const.

Para evitar la duplicación de código, existe la tentación de llamar a un método desde otro. Sin embargo, no podemos llamar al método non-const del const. Pero podemos llamar al método const desde el no const. Eso requerirá usar "const_cast" para eliminar el calificador const.

La solucion es:

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

En el código anterior, llamamos a la versión const de GetBar desde GetBar no const al GetBar esto en tipo const: const_cast<const Foo*>(this) . Como llamamos al método const desde non-const, el objeto en sí mismo es non-const y se permite desechar la const.

Examina el siguiente ejemplo más 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
Licenciado bajo CC BY-SA 3.0
No afiliado a Stack Overflow