2011-01-12 31 views
35

Digamos que tengo una clase definida de la siguiente manera:declarar una instancia de una clase const

class foo{}; 

ahora, esto es perfectamente aceptable;

foo f; 

¿cómo es que esto es un error de compilación? (uninitialized const ‘f’)

const foo f; 

¿Por qué tenemos que hacer esto?

const foo f = foo(); 

sé por qué no podemos hacer esto ..

const foo f(); // though it compiles.. 

Curiosamente, es válido lo siguiente:

const std::string f; 

Así que lo que falta en foo?

Me doy cuenta de que hay tres preguntas allí y es mala forma, pero espero que alguien pueda aclararme esto en una respuesta.

EDIT: no dude en cerrarla si es estúpida ...

+5

Por cierto, he visto muchas preguntas estúpidas sobre Stack Overflow. La tuya * no * es una pregunta estúpida de ninguna manera. –

+0

@Konrad Rudolph, estaba sentado allí rascándome la cabeza, y normalmente cuando eso me sucede, es inevitable porque he hecho algo estúpido ... :) – Nim

Respuesta

46

Su clase es un POD (básicamente porque no proporciona un constructor por defecto). Las variables POD son no inicializadas a la declaración. Es decir, esto:

foo x; 

no inicializa x a un valor significativo. Esto debe hacerse por separado. Ahora, cuando lo declara como const, esto puede que nunca ocurra porque ya no puede asignar o cambiar x.

en cuenta la equivalencia de int:

int x; // legal 
const int y; // illegal 

Como usted ha notado, utilizando std::string en lugar de foo compila. Eso es porque std::string no es un POD. Una solución simple a su dilema es proporcionar un constructor por defecto para foo:

class foo { 
public: 
    foo() { } 
}; 

ahora compila su código const foo x;.

+0

@Konrad lo que es realmente interesante es que gcc es el único que da un error. Cuando probé esto con otros compiladores como msvc, CodeGear y digital mars, todos compilaron sin quejas. ¿Es este comportamiento no conforme con los estándares? – greatwolf

+0

@Victor: ¿realmente se aseguró de que la clase 'foo' fuera un POD (es decir, al no tener ningún miembro)? Si es así, entonces sí, esos compiladores no son estándares compilantes. Este código no debería compilarse. –

+0

@Konrad sí, foo es solo una estructura vacía. Tenía una versión con y sin un constructor predeterminado. Acabo de probar esto con Comeau y correctamente atrapa esto también. Entonces parece que solo gcc y comeau están en conformidad. – greatwolf

1

const, aplicado a una variable sencilla de datos antiguos, indica que esa variable no cambiará en ese contexto, por lo que no podrá reasignarla a algo. Por lo tanto, debe inicializarlo o será perpetuamente no inicializado y, por lo tanto, inútil.

+0

"_aplicado a una simple variable de datos antiguos, indica que esa variable no cambiará en ese contexto_" y con un elemento que no sea POD, ¿significa menos? ;) [Sugerencia: no] – curiousguy

1

Creo que hay más alternativas. Usted puede hacer

const foo f={}; 

o

const foo f(()); 

Const significa que no se puede asignar a ella más tarde, así que hay que inicializarlo.Como no definió el constructor predeterminado, el compilador supone que tiene que ser inicializado por usted. std :: string tiene un constructor predeterminado, por lo que el compilador lo llama implícitamente.

+0

Pero las dos formas no son equivalentes en general: la primera forma inicializará todos los miembros de 'foo' a 0 (convenientemente convertidos), la segunda forma inicializará el valor' f': llamará al constructor predeterminado si hay uno, o bien va a inicializar el valor de cada miembro: llame al constructor predeterminado para el miembro, si hay uno, o inicialice el valor de cada miembro del agregado, si es un agregado, o inicialice el miembro a 0 (convenientemente convertido). – curiousguy

+0

"' const foo f (()); '" no es una sintaxis válida –

6

Es un problema conocido generar un error en la situación de una clase vacía, y se reporta como issue #253.

Cuestiones relacionadas