C++
palabra clave const
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';
}