2008-11-06 11 views
8

Si hago esto:C++ pregunta const

// In header 
class Foo { 
void foo(bar*); 
}; 

// In cpp 
void Foo::foo(bar* const pBar) { 
//Stuff 
} 

El compilador no se queja de que las firmas para Foo :: foo no coinciden. Sin embargo si tuviera:

void foo(const bar*); //In header 
void Foo::foo(bar*) {} //In cpp 

El código no podrá compilarse.

¿Qué está pasando? Estoy usando gcc 4.1.x

+0

¿Quería poner la const en el otro lado del * en su segundo ejemplo? Algunas personas responden explicando la diferencia en el significado de eso, y otras responden explicando la diferencia en si const está en el archivo cpp o h. –

+0

Debe elegir una respuesta a su pregunta o actualizarla si no es la respuesta que está buscando. –

Respuesta

1

La palabra clave const en el primer ejemplo no tiene sentido. Usted dice que no planea cambiar el puntero. Sin embargo, el puntero se pasó por valor y, por lo tanto, no importa si lo cambia o no; no afectará a la persona que llama. Del mismo modo, también se puede hacer esto:

// In header 
class Foo { 
void foo(int b); 
}; 

// In cpp 
void Foo::foo(const int b) { 
//Stuff 
} 

Incluso puede hacer esto:

// In header 
class Foo { 
void foo(const int b); 
}; 

// In cpp 
void Foo::foo(int b) { 
//Stuff 
} 

Desde el int se pasa por valor, el constness no importa.

En el segundo ejemplo, usted dice que su función toma un puntero a un tipo, pero luego lo implementa tomando un puntero a otro tipo, por lo tanto falla.

15

En el primero, ha prometido al compilador, pero no a otros usuarios de la clase, que no editará la variable.

En su segundo ejemplo, ha prometido a otros usuarios de la clase que no editarán su variable, pero no cumplieron esa promesa.

También debo señalar que hay una clara diferencia entre

bar* const variable 

y

const bar* variable 

y

const bar* const variable 

En la primera forma, el puntero no va a cambiar, pero puede editar el objeto al que apunta. En la segunda forma, puede editar el puntero (señalarlo a otro objeto), pero nunca la variable a la que apunta. En la forma final, no editarás el puntero ni el objeto al que apunta. Reference

Para agregar un poco más de aclaración a la pregunta planteada, siempre se puede prometer MÁS const que menos. Dada una clase:

class Foo { 
    void func1 (int x); 
    void func2 (int *x); 
} 

puede compilar la siguiente implementación:

Foo::func1(const int x) {} 
Foo::func2(const int *x) {} 

o:

Foo::func1(const int x) {} 
Foo::func2(const int* const x) {} 

sin ningún problema. Les ha dicho a sus usuarios que posiblemente puedan editar sus variables. En su implementación, le dijo al compilador que esta implementación particular no editará esas variables, aunque le haya dicho a los usuarios que podría hacerlo. No has incumplido una promesa para el usuario, por lo que el código se compila.

+0

No creo que su teoría sea válida: 1) Si declara "int *" e implementa "const int *", como en su ejemplo, no se compila. 2) Si pasa por valor, puede declarar const y no implementar con const. No tiene sentido cuando pasas por valor. –

+0

sí. estoy de acuerdo que estás equivocado void f (int const *); es diferente de void f (int *); Creo que querías escribir void f (int * const); tiene la misma firma que void f (int *); Deberías cambiar tu ejemplo ya que podría confundir a los principiantes. –

0

En el primero, el const no afecta a la interfaz, solo a la implementación. Le está diciendo al compilador, "No voy a cambiar el valor del bar* dentro de esta función". Aún puede cambiar lo que señala el puntero. En este último, le está diciendo al compilador (y a todas las personas que llaman) que no cambiará la estructura bar que bar*apunta a.

+0

Creo que quieres decir en la última oración "no modificarás la barra a la que apunta la barra *". "Cambiar lo que señala la barra *" podría interpretarse como "dar a la barra * un nuevo valor", lo cual está bien en el segundo ejemplo. –

+0

Gracias por eso, corregido. Los pronombres son la perdición de la claridad. –

6

Ver this question, this question y this question.

Básicamente, la const solo significa que la función no modificará el valor del puntero. Los contenidos de los punteros no son const, lo mismo que la firma del encabezado.

0

Así que la segunda const en:

void Foo::foo(const bar* const); 

Es no parte de la firma del método?

+1

Declara un método en el archivo .h, lo define en .cpp.Todo en la declaración es parte de la firma (ambas constelaciones), parece que en la definición se puede refinar más el tipo de argumento siempre que esa definición no rompa la semántica de la declaración. –

+0

@mamin: Correcto. Por ejemplo, observe el error del vinculador que obtiene si declara (pero no define) una función "void foo (const int * const a)", y luego lo llama. La firma notificada falta por GCC es "foo (int const *)". –

+0

simple: si agrega/elimina const, no será parte de la firma. tan vacío foo (int * const); y void foo (int *); de hecho tienen la misma firma. PERO void foo (int const *); y void foo (int *); tienen diferentes firmas: no se agrega const al tipo de parámetro, sino al tipo al que se apunta. –

0

Esto es más simple de entender con un tipo de variable que no sea un puntero. Por ejemplo, puede tener la siguiente declaración de la función:

void foo(int i); 

La definición puede tener este aspecto:

void foo(const int i) { ... } 

si la variable 'i' es const o no en el lado definición es un detalle de implementación . No tiene impacto para los clientes de esa función.

+0

no entiendo cómo votan los usuarios de SO. arriba votada con +15 arriba es una respuesta que tiene una declaración incorrecta al final y no tiene ganas de arreglarla (la persona se lo dijo hace 3 meses), y en -1 esta respuesta está bien y se explica mucho mejor (EN MI HUMILDE OPINIÓN). haciendo +1 por el bien de la equidad. –

+0

De acuerdo. No entiendo por qué fui rechazado por esta respuesta ... –

0

Probablemente no se preocupe demasiado por void Foo::foo(bar* const pBar) porque la forma en que se trata el puntero (const o no) no importa un poco fuera de la rutina. Las reglas de C dicen que ningún cambio en pBar viajará fuera de foo de ninguna manera.

Sin embargo, si es (const bar* pBar), eso hace la diferencia, porque significa que el compilador no permite que las personas que llaman pasen punteros a objetos no const.