2009-04-01 15 views
5

Tenía el siguiente código C++, donde el argumento para mi constructor en la declaración tenía una constness diferente a la definición del constructor.Falta de coincidencia entre la definición del constructor y la declaración

//testClass.hpp 
class testClass { 
    public: 
    testClass(const int *x); 
}; 

//testClass.cpp 
testClass::testClass(const int * const x) {} 

que era capaz de compilar esta sin advertencias utilizando g ++, debe este código de compilación o al menos dar algunas advertencias? Resulta que el compilador C++ incorporado en los Solaris de 64 bits me dio un error de enlazador, que es como noté que había un problema.

¿Cuál es la regla sobre los argumentos coincidentes en este caso? ¿Depende de los compiladores?

Respuesta

7

En casos como este, el especificador const puede ser ommitt ed desde la declaración porque no cambia nada para la persona que llama.

Importa solo en el contexto de los detalles de implementación. Es por eso que está en la definición pero no en la declaración .

Ejemplo:

//Both f and g have the same signature 
void f(int x); 
void g(const int x); 

void f(const int x)//this is allowed 
{ 
} 

void g(const int x) 
{ 
} 

alguien que llame a f no le importa que se va a tratar como constante porque es su propia copia de la variable.

Con int * const x, es lo mismo, es su copia del puntero. Si puede señalar algo más no le importa a la persona que llama.

Si omitió la primera función en const int * const, entonces eso marcaría la diferencia porque le importa a la persona que llama si cambia los datos a los que apunta.

Referencia: El C++ estándar, 8.3.5 párrafo 3:

"se elimina Cualquier cv-calificador modificar un tipo parámetro ... Tales CV-calificadores afectan sólo a la definición del parámetro con el cuerpo de la función, sino que no afectan el tipo de función"

+0

Indique la referencia al Estándar. –

+0

He escrito sobre esto aquí, si necesita más ejemplos: http://stackoverflow.com/questions/269882/c-const-question/274888#274888 –

+0

@ onebyone.livejournal.com: Gracias. –

4

pensar en ella como la misma diferencia entre

//testClass.hpp 
class testClass { 
    public: 
    testClass(const int x); 
}; 

//testClass.cpp 
testClass::testClass(int x) {} 

Lo que también compila. No puede sobrecargar en función de la constidad de un parámetro de valor por paso. Imagínese este caso:

void f(int x) { } 
void f(const int x) { } // Can't compile both of these. 

int main() 
{ 
    f(7); // Which gets called? 
} 

de la norma:

declaraciones de parámetros que difieren sólo en la presencia o ausencia de const y/o volátil son equivalentes. Es decir, los tipos y especificadores const y volátiles para cada tipo de parámetro se ignoran al determinar cuya función se está declarando, definida o llamada. [Ejemplo:

typedef const int cInt; 
int f (int); 
int f (const int); // redeclaration of f(int) 
int f (int) { ... } // definition of f(int) 
int f (cInt) { ... } // error: redefinition of f(int) 

-end ejemplo] Sólo el const y volátiles de tipo especificadores en el nivel más exterior del tipo de parámetro especificación se ignora en este moda; const y volátiles tipo especificadores enterrados dentro de una especificación de tipo parámetro son significativa y se pueden usar para distinguen la función sobrecargado declarations.112) En particular, para cualquier tipo T, “puntero a T,” “puntero a const T,”y‘puntero a volátil T’se consideran distintos tipos de parámetros, como son‘referencia a T’,‘referencia a const T’, y ‘referencia a T. volátil’

0

Es const int * const x no es lo mismo que const int * x porque ya tienes const?

+0

No. En el primer caso, x es un puntero const para un entero const. En el segundo caso, x es un puntero * non-const * a un entero const. –

+0

Específicamente, en primer lugar, puede modificar ni x ni * x. En el segundo caso, no puede modificar x *, pero puede modificar x. Por ejemplo, el segundo podría usarse para recorrer una matriz (con x ++, por ejemplo), y el primero no podría. –

5

Este ejemplo está cubierto de forma explícita en la sección de resolución de sobrecarga, 13,1/3B4:

declaraciones de parámetros que difieren sólo en la presencia o ausencia de const y/o volátiles son equivalente. Es decir, los especificadores de tipos const y volátiles para cada tipo de parámetro se ignoran al determinar qué función se declara, define o llama.

[Ejemplo:

typedef const int cInt; 
int f (int); 
int f (const int); // redeclaration of f(int) 
int f (int) { ... } // definition of f(int) 
int f (cInt) { ... } // error: redefinition of f(int) 

-fin ejemplo]

lo tanto, es sin duda está bien.

Cuestiones relacionadas