2009-08-21 15 views
6
struct A { 
    static const int a = 5; 

    struct B { 
     static const int b = a; 
    }; 

}; 

int main() { 
    return A::B::b; 
} 

El código anterior se compila. Sin embargo, si opta por el libro Effective C++ de Scott Myers (pg 14); Necesitamos una definición para a, además de la declaración. ¿Alguien puede explicar por qué esto es una excepción?utilizando una interfaz estática int en una estructura/clase

+1

El código _doses_ contiene una definición para 'a'. –

+2

No, no contiene una definición. –

+1

@Henk. Realmente no. Intente pasar la dirección de 'a' o 'b' a una función y vea qué mensaje genera el compilador. –

Respuesta

18

Los compiladores de C++ permiten que los enteros estáticos const (solo los enteros) tengan su valor especificado en la ubicación en que se declaran. Esto se debe a que la variable esencialmente no es necesaria, y vive solo en el código (normalmente se compila).

Otros tipos de variables (como static const char *) normalmente no se pueden definir donde se declaran y requieren una definición separada.

Para obtener una explicación un poco más detallada, tenga en cuenta que para acceder a una variable global, normalmente es necesario hacer una referencia de dirección en el código de nivel inferior. Pero su variable global es un número entero cuyo tamaño es típicamente del tamaño de una dirección, y el compilador se da cuenta de que nunca cambiará, entonces, ¿por qué molestarse en agregar la abstracción del puntero?

+0

+1, buena respuesta. Pero, ¿y si 'const' enteros? ¿Podemos especificar su valor en clase? – Alcott

+0

no "enteros", solo expresión constante – czxyl

18

Por reglas realmente pedantes, sí, su código necesita una definición para ese entero estático. Pero, según las reglas prácticas, y lo que implementan todos los compiladores, porque así es como están diseñadas las reglas de C++ 03, no, no necesita una definición.

Las reglas para tales enteros constantes estáticos están destinadas a permitirle omitir la definición si el entero se usa solo en situaciones donde un valor se lee inmediatamente, y si el miembro estático se puede usar en expresiones constantes.

En su declaración de devolución, el valor del miembro se lee inmediatamente, por lo que puede omitir la definición del miembro entero constante estático si ese es el único uso de la misma. Sin embargo, la siguiente situación necesita una definición:

struct A { 
    static const int a = 5; 

    struct B { 
     static const int b = a; 
    }; 

}; 

int main() { 
    int *p = &A::B::b; 
} 

No se lee ningún valor aquí, pero en su lugar se toma la dirección. Por lo tanto, la intención del Estándar C++ 03 es que debe proporcionar una definición para el miembro como la siguiente en algún archivo de implementación.

const int A::B::b; 

Tenga en cuenta que los reglas actuales que aparecen en el C++ 03 estándar dice que no es necesaria una definición única, donde se utiliza la variable en una expresión constante es necesaria . Sin embargo, esa regla, si se aplica estrictamente, es demasiado estricta. Solo le permitiría omitir una definición para una situación como dimensiones de matriz, pero requeriría una definición en casos como una declaración de devolución. El informe de defectos correspondiente es here.

La redacción de C++ 0x se ha actualizado para incluir la resolución del informe de defectos y permitir el código tal como está escrito.

+0

¿Significa que Walt W está equivocado cuando dice: "Los compiladores C++ permiten que los enteros estáticos const (solo enteros) se definan en la ubicación en que se declaran"? Pensé como él que el "static const int a = 5;" declaración fue a la vez declaración y definición. Si lo entiendo correctamente, es solo una declaración sin ninguna definición y el A :: a solo puede usarse en casos muy específicos. Estoy interesado en la última palabra ... – neuro

+0

Sí, él también está equivocado. Esa es solo una declaración, no es una definición. Si se refiere a él en casos que no lee un valor inmediatamente, se necesita una definición. Parece que lo tienes bien en tu comentario. –

+0

¿Mejor? Supongo que no fue el uso técnico de la "definición" –

0

En general, la mayoría (y reciente) compiladores de C++ permiten enteros const estáticos

Usted acaba de suerte, tal vez no. Pruebe un compilador anterior, como gcc 2.0, y lo castigará con vehemencia con un mensaje de error que no sea tan bonito.

1

Sin embargo, si se intenta el operando ternaria sin "definir" consts estáticas, se obtiene un error de enlazador de GCC 4x:

http://gcc.gnu.org/bugzilla/show_bug.cgi?id=13795

Por lo tanto, aunque las construcciones como int k = A::CONSTVAL; son ilegales en la norma actual, son compatibles. Pero el operando ternario no lo es. Algunos operadores son más iguales que otros, si entiendes :)

Muchas reglas "laxas". Te sugiero que escribas un código que se ajuste al estándar si no quieres sorpresas.

Cuestiones relacionadas