2010-01-28 5 views
17

He visto muchos usos de la palabra clave const puesto después de las funciones en las clases, así que quería saber de qué se trataba. Leí algo aquí: http://duramecho.com/ComputerInformation/WhyHowCppConst.html.Usando 'const' en las funciones de la clase

Dice que const se usa porque la función "puede intentar alterar cualquier variable miembro en el objeto". Si esto es cierto, entonces debe usarse en todas partes, porque no quiero que ALGUNA de las variables miembro se altere o cambie de ninguna manera.

class Class2 
{ void Method1() const; 
    int MemberVariable1;} 

Entonces, ¿cuál es la definición real y el uso de const?

+3

Si sus variables miembro nunca cambian, ¿por qué tiene variables miembro? –

+6

¿Porque quiere una clase que sea inmutable? Esto no es irracional. –

+1

No soy realmente una persona de C++, por lo que era más una cuestión de interés que una pregunta "gotcha". ¿Por qué no declararías a todos tus miembros "const" si quisieras que fuera realmente inmutable? ¿O ambos declararían a los miembros como const y los métodos como const? –

Respuesta

29

Un método const puede ser llamado en un objeto constante:

class CL2 
{ 
public: 
    void const_method() const; 
    void method(); 

private: 
    int x; 
}; 


const CL2 co; 
CL2 o; 

co.const_method(); // legal 
co.method();  // illegal, can't call regular method on const object 
o.const_method(); // legal, can call const method on a regulard object 
o.method();   // legal 

Además, también le dice al compilador que el método const no se debe cambiar el estado del objeto y cogerá esos problemas:

void CL2::const_method() const 
{ 
    x = 3; // illegal, can't modify a member in a const object 
} 

Hay una excepción a la regla anterior mediante el uso del modificador mutable, pero primero debe obtener buenos resultados const correctness antes de aventurarse en ese territorio.

+0

¿Debería uno, por seguridad, proporcionar const para todos los métodos que no se espera que cambien el estado del objeto? (getters, por ejemplo) – gen

+0

Para const corrección, sí. – U007D

1

Si esto es cierto, ¿debería usarse en todas partes, porque no quiero que ALGUNA de las variables miembro se altere o cambie de alguna manera?

Bueno, no. A veces, usted do quiere métodos de instancia para modificar miembros. Por ejemplo, cualquier método establecido obviamente necesitará establecer variables, por lo que no es el caso que deba poner const en todas partes. Pero si el estado de su objeto es totalmente inmutable, primero considere si no sería mejor no tener instancias (es decir, una clase estática), y si ese no es el caso, haga todo const.

2

El significado es que garantiza a los clientes que llaman a un miembro de la función const que el estado del objeto no cambiará. Por lo tanto, cuando dice que una función miembro es const, significa que no cambia ninguna de las variables miembro de los objetos durante la llamada a la función.

+0

Eso no es del todo cierto: el comportamiento observable no cambia, pero los datos de los miembros pueden marcarse como 'mutable'. Esto permite el almacenamiento en caché de resultados calculados una sola vez, por ejemplo. –

+0

Es aún peor. Si tiene un puntero apuntando a algunos datos, el 'const' detrás de una función miembro solo garantiza que el puntero no se cambia, no los datos a los que apunta. A menudo, sin embargo, los datos se consideran parte del estado del objeto. Entonces, en realidad, ese 'const' solo evita que una función miembro cambie los datos del miembro del objeto, no todo su estado. Implica constness bit-wise, no constness lógica. – sbi

+0

De hecho, solo aplica constness bitwise, y todas las apuestas están desactivadas cuando establece un miembro mutable. Es solo una pista para el compilador, el Sr. Klatchko tiene una mejor explicación anterior. – mikelong

2

Es bastante inusual no querer que se cambien las variables de miembro, pero si eso es lo que su clase requiere, entonces debe hacer todas las funciones de miembro const.

Sin embargo, es probable que desee cambiar al menos algunos miembros:

class A { 
    private: 
    int val; 
    public: 
    A() : val(0) {} 
    void Inc() { val++; } 
    int GetVal() const { return val; }; 
}; 

Ahora bien, si puedo crear dos instancias de A:

A a1; 
const A a2; 

lo que puedo decir:

a1.GetVal(); 
a2.GetVal(); 

pero solo puedo decir:

a1.Inc(); 

tratar de cambiar el valor de un objeto constante:

a2.Inc(); 

da un error de compilación.

+0

Los métodos que no cambian el estado externo son más comunes en la programación declarativa; no es la manera más fácil de hacerlo en C++ en este momento. Pero los diseños de bibliotecas de C++ más fluidos están en camino (por ejemplo, [Ranges v3] (https://github.com/ericniebler/range-v3)) que harán que esto sea más práctico en el futuro. – U007D

1

La palabra clave const utilizada después de un método indica que este método no modifica el objeto al que se llama. De esta forma, este método se puede invocar en una versión constante del objeto.

3

Const, cuando está conectado a un método de clase no estático, le dice al compilador que su función no modifica el estado interno del objeto.

Esto es útil en dos sentidos:

  • Si escribir código que cambia de estado interno de su método const, el compilador captura el error, moviendo un error de programación de tiempo de ejecución a tiempo de compilación.
  • Si el código del cliente llama a un método no const en un puntero constante, el compilador detecta el error, asegurando que se mantiene la "cadena de no cambiar cosas".

Normalmente desea declarar todos los métodos de clase no mutantes no estáticos como const. Esto permite que el código de llamada use el calificador const en los punteros, y ayuda a detectar errores.

C++ típico: puede declarar una variable de miembro de clase "mutable" y luego cambiarla incluso desde un método const.

3

Otros han respondido al aspecto técnico de su pregunta acerca de las funciones de miembros de const, pero aquí hay una idea más amplia, y esa es la idea de const correctness.

En pocas palabras, la precisión de la precisión se trata de aclarar y aplicar la semántica de su código. Tome un ejemplo simple. Mire esta declaración de función:

bool DoTheThing(char* message); 

Supongamos que alguien más escribió esta función y necesita llamarla. ¿Sabes lo que DoTheThing() hace a tu buffer de char? Tal vez solo registra el mensaje en un archivo, o tal vez cambia la cadena. No se puede decir cuál es la semántica de la llamada con solo mirar la declaración de la función. Si la función no modifica la cadena, entonces la declaración es const incorrecta.

Tiene un valor práctico para hacer que sus funciones también sean correctas. A saber, dependiendo del contexto de la llamada, es posible que no pueda llamar a las funciones incorrectas sin ningún truco. Por ejemplo, supongamos que usted sabe que DoTheThing() no modifica el contenido de la cadena que se le pasa, y usted tiene este código:

void MyFunction() 
{ 
    std::string msg = "Hello, const correctness"; 
    DoTheThing(msg.c_str()); 
} 

El código anterior no compilará porque msg.c_str() devuelve un const char*. Con el fin de obtener este código para compilar, tendría que hacer algo como esto:

void MyFunction() 
{ 
    std::string msg = "Hello, const correctness"; 
    DoTheThing(msg.begin()); 
} 

... o peor aún:

void MyFunction() 
{ 
    std::string msg = "Hello, const correctness"; 
    DoTheThing(const_cast<char*>(msg.c_str())); 
} 

ninguno de los cuales, sin duda, es 'mejor' que el código original. Pero debido a que DoTheThing() se escribió de manera incorrecta, tiene que doblar su código alrededor de él.

Cuestiones relacionadas