class String
{
private:
char* rep;
public:
String (const char*);
void toUpper() const;
};
String :: String (const char* s)
{
rep = new char [strlen(s)+1];
strcpy (rep, s);
}
void String :: toUpper() const
{
for (int i = 0; rep [i]; i++)
rep[i] = toupper(rep[i]);
}
int main()
{
const String lower ("lower");
lower.toUpper();
cout << lower << endl;
return 0;
}
Respuesta
Un método constante, es una función miembro que no muta sus variables miembro.
const en una función miembro no implica const char *. Lo que significaría que no puede cambiar los datos en la dirección que contiene el puntero.
Su ejemplo no muta las variables de los miembros.
Const en una función de miembro, se asegurará de tratar todas las variables de miembro como const.
Esto significa que si usted tiene:
int x;
char c;
char *p;
entonces usted tendrá que:
const int x;
const char c;
char * const p; //<-- means you cannot change what p points to, but you can change the data p points to
Hay 2 tipos de punteros const. Una función miembro miembro usa la que he enumerado arriba.
Una manera de obtener el error que desea:
pruebe a cambiar:
char * rep;
a:
char rep[1024];
Y elimine esta línea:
rep = new char [strlen(s)+1];
Se lanzará el error que está esperando (no se puede modificar porque los miembros de palabra clave const)
Porque sólo hay 1 tipo de matriz const. Y eso significa que no puedes modificar ninguno de sus datos.
Ahora todo el sistema es en realidad roto con el siguiente ejemplo:
class String
{
private:
char rep2[1024];
char* rep;
...
String :: String (const char* s)
{
rep = rep2;
strcpy (rep, s);
}
Así que la lección a aprender aquí es que la palabra clave const en funciones miembro no asegura que el objeto no cambiará en absoluto.
Solo garantiza que cada variable miembro se tratará como const. Y para los indicadores, hay una gran diferencia entre const char * y char * const.
La mayor parte del tiempo una función miembro miembro significa que la función miembro no modificará el objeto en sí, pero este no es siempre el caso, como se muestra en el ejemplo anterior.
toUpper() no cambia el puntero (que pertenece a la clase). Solo cambia los datos a los que señala rep (que no pertenecen a la clase).
Sin embargo, 'const' es una especie de garantía para los usuarios de su clase: si se declara un método const, quien usa una instancia de su clase puede esperar que no cambie al llamar al método. Mi punto es que si toUpper() cambia el estado de una cadena, no lo declare, ya sea que C++ lo permita o no.
El calificador const significa que no cambiará ningún miembro de la clase.
En este caso rep es el único miembro de la clase y no veo ningún intento de modificar este miembro. Cualquier cosa apuntada a o con referencia fuera de la clase no se considera como parte de la clase.
Una solución a este problema sería reemplazar el char * con std :: string.
Entonces sólo sería capaz de llamar a los miembros de const std :: string desde dentro toUpper()
Por ejemplo (uso std :: string)
class String
{
std::string rep;
void toUpper() const
{
for (int i = 0; rep [i]; i++)
rep[i] = toupper(rep[i]);
// Can only use const member functions on rep.
// So here we use 'char const& std::string::operator[](size_t) const'
// There is a non const version but we are not allowed to use it
// because this method is const.
// So the return type is 'char const&'
// This can be used in the call to toupper()
// But not on the lhs of the assignemnt statement
}
}
La razón es que no cambia rep
. Si lo hiciera, encontraría rep = ...;
en algún lugar de su código. Esta es la diferencia entre
char*const rep;
y
const char* rep;
En su caso, el primero se realiza si se ejecuta un miembro de función const: El puntero es const. Por lo tanto, no podrá restablecer el puntero. Pero muy bien podrá cambiar a lo que apunta el puntero.
Ahora, recuerde rep[i] = ...;
es lo mismo que *(rep + i) = ...;
. Por lo tanto, lo que cambie no es el puntero, sino lo que el puntero apunta a. Está permitido, ya que el puntero no es del segundo tipo de caso.
Solución
- La const lo que significa que está viendo es
physical constness
. Sin embargo, una función de miembro const significa que su objeto eslogical const
. Si un cambio en algún contenido cambiará el constness lógica de su objeto, por ejemplo, si cambia alguna variable estática de la que depende su objeto, su compilador no puede saber que su clase ahora tiene otro valor lógico.Y tampoco puede saber que el valor lógico cambia dependiendo de a qué apunta un puntero: El compilador no intenta verificar la constidad lógica en una función de miembro constante, ya que no puede saber lo que significan esas variables miembro. Esto se denominaconst-correctness
. - Use un objeto que no sea solo una referencia o un puntero: una función de miembro const hará que ese objeto sea const, y no le permitirá cambiar su contenido.
std::string
, tal como lo propusieron algunos, o una matriz de caracteres (tenga en cuenta que una matriz le impedirá cambiar su contenido, en lugar de solo un puntero), sería una opción adecuada. 2.
No se puede cambiar el valor de algo declarada como
const char* rep;
o
const char* const rep;
Desafortunadamente, declarando su const miembro se convierte en representante en
char* const rep;
lo que significa que no puedes c cuelgue la dirección acutal, pero puede cambiar el contenido, mientras que no puede cambiar el valor.
Para hacer que los const memebrs respeten mantener su const buffer, tendrá que hacer rep y una matriz de caracteres o un objeto de cadena en lugar de un puntero de carácter.
- 1. ¿Por qué is_lock_free es una función miembro?
- 2. Miembro por copia del miembro
- 3. Encuadernación a una variable miembro
- 4. Función miembro que devuelve una variable estática
- 5. ¿Cuál es la semántica de una función miembro miembro?
- 6. Variable global estática utilizada por la función miembro en línea
- 7. ¿Diferencia entre la variable miembro y la propiedad miembro?
- 8. variable estática frente a miembro
- 9. Constructor no establece variable miembro
- 10. miembro definición de función
- 11. Funciones de miembro no miembro frente a miembro en Python
- 12. variable de miembro de captura por valor
- 13. Puntero de función de miembro
- 14. Llamar a una función de miembro no const desde una función de miembro constante
- 15. Objeto inmutable con la variable miembro ArrayList: ¿por qué se puede cambiar esta variable?
- 16. Anulando una variable miembro en C++
- 17. unary minus overload: miembro o no miembro?
- 18. ¿Ventajas de utilizar una función miembro estática en lugar de una función miembro no estático equivalente?
- 19. ¿Cómo obtener anotaciones de una variable miembro?
- 20. variable miembro python de instancia funciona como variable miembro, y algunos funciona como variable estática
- 21. ¿Por qué JAXB no permite anotaciones en getters que todos extraen de la misma variable miembro?
- 22. ¿Cuándo se destruye esta variable de miembro VB6?
- 23. ¿Referencia a la función miembro?
- 24. QtConcurrent con función de miembro
- 25. Puntero como miembro o Referencia como miembro
- 26. Puntero de función a función de miembro
- 27. ¿Miembro estático de una función en Python?
- 28. ¿Por qué Perl no me permite desreferenciar un miembro de una referencia hash en una matriz?
- 29. función miembro que oculta la función libre
- 30. No puedo entender esta línea: desreferenciar una dirección de variable de miembro privado o qué?
Muchas gracias por la respuesta rápida y la delineación muy ordenada. Stack Overflow realmente rocas – mahesh