2010-09-13 20 views
44

Me gustaría saber cuál es la diferencia entre las variables estáticas en un archivo de encabezado frente a las declaradas en una clase. Cuando la variable estática se declara en un archivo de cabecera, su alcance se limita al archivo .h o en todas las unidades. Además, en general, la variable estática se inicializa en el archivo .cpp cuando se declara en una clase, ¿verdad? Entonces, ¿eso significa que el alcance de la variable estática está limitado a 2 unidades de compilación?Variables estáticas en C++

+5

La palabra clave 'estática' está muy sobrecargada.Significa diferentemente en diferentes lugares. Es por eso que es una pregunta divertida para hacer en las entrevistas. – vrdhn

+0

Definitivamente entre los mejores, junto con funciones abstractas/clases abstractas, y cosas como herencia pública/protegida/privada. ;-) – DevSolar

Respuesta

67

Disculpe, cuando respondo a sus preguntas fuera de orden, lo hace más fácil de entender de esta manera.

Cuando la variable estática se declara en un archivo de cabecera, su alcance se limita al archivo .h o en todas las unidades.

No existe el "alcance del archivo de encabezado". El archivo de encabezado obtiene incluido en archivos fuente. La unidad de traducción es el archivo de origen que incluye el texto de los archivos de encabezado. Todo lo que escriba en un archivo de encabezado obtiene copiado en cada archivo fuente incluido.

Como tal, una variable estática declarada en un archivo de encabezado es como una variable estática en cada archivo fuente individual.

Desde declarar una variable static esta manera significa enlace interno, cada unidad de traducción #include ing su archivo de cabecera recibe su propia , variable individual (que no es visible fuera de su unidad de traducción). Esto usualmente no es lo que quieres.

Me gustaría saber cuál es la diferencia entre las variables estáticas en un archivo de encabezado contra declarado en una clase.

En una declaración de clase, static significa que todas las instancias de la clase cuota de esta variable miembro; es decir, puede tener cientos de objetos de este tipo, pero cada vez que uno de estos objetos se refiere a la variable static (o "clase"), tiene el mismo valor para todos los objetos. Podrías pensar que es una "clase global".

También generalmente la variable estática se inicializa en el archivo .cpp cuando se declara en una clase, ¿verdad?

Sí, una unidad (y sólo uno ) traducción debe inicializar la variable de clase.

Entonces, ¿eso significa que el alcance de la variable estática está limitado a 2 unidades de compilación?

Como ya he dicho:

  • Un encabezado no es una unidad de compilación,
  • static significa cosas completamente diferentes dependiendo del contexto.

Global static limita el alcance a la unidad de traducción. La clase static significa global para todas las instancias.

Espero que esto ayude.

PS: Compruebe el último párrafo de la respuesta de Chubsdad, acerca de cómo no se debe utilizar static en C++ para indicar enlace interno, pero los espacios de nombres anónimos. (Porque tiene razón; ;-))

+6

"estático significa cosas completamente diferentes según el contexto". -> la fuente misma de la mayor confusión al respecto. Esta mentalidad de "no agregar palabras clave" es realmente molesta :( –

+0

@Matthieu M. Depende de su punto de vista.Para mantener cierta compatibilidad entre C y C++, es muy beneficioso. Admito, sin embargo, que se han exagerado un poco con ' static'. – DevSolar

+0

Sé que era necesaria la compatibilidad, de lo contrario el lenguaje no habría sido tan popular. Sin embargo, podrían haber usado una nueva palabra clave para el significado de C++, podrían haberlo convertido en "no palabra clave" fuera de una clase/struct scope para preservar la compatibilidad con versiones anteriores. Me alegra que hayan introducido la palabra clave 'nullptr' en C++ 0x. –

38

Variable estática en un archivo de cabecera:

dicen 'common.h' tiene

static int zzz; 

Esta variable 'zzz' ha enlazado interno (Esta misma variable no se puede acceder en otras unidades de traducción). Cada unidad de traducción que incluye 'common.h' tiene su propio objeto único con el nombre 'zzz'.

Variable estática en una clase:

Variable estática en una clase no es una parte del subobjeto de la clase. Solo hay una copia de un miembro de datos estáticos compartida por todos los objetos de la clase.

$ 9.4.2/6 - "los miembros de datos estáticos de una clase en el perímetro de espacio de nombres tienen vinculación clase local externa (3.5) .A no tendrá miembros de datos estáticos".

Digamos que tiene 'myclass.h'

struct myclass{ 
    static int zzz;  // this is only a declaration 
}; 

y myclass.cpp tiene

#include "myclass.h" 

int myclass::zzz = 0   // this is a definition, 
           // should be done once and only once 

y "hisclass.cpp" tiene

#include "myclass.h" 

void f(){myclass::zzz = 2;} // myclass::zzz is always the same in any 
           // translation unit 

y "ourclass.cpp" tiene

#include "myclass.h" 
void g(){myclass::zzz = 2;} // myclass::zzz is always the same in any 
           // translation unit 

Por lo tanto, los miembros estáticos de la clase no están limitados a solo 2 unidades de traducción. Deben definirse solo una vez en cualquiera de las unidades de traducción.

Nota: el uso de 'estática' para declarar archivo está en desuso variable de alcance y espacio de nombres sin nombre es un alternativo

+1

muchas gracias por una buena respuesta. – brett

+1

"Cada archivo que incluye" ... es bastante inexacto, ya que los archivos de encabezado pueden incluir otros archivos de encabezado. Mejor seguir con la frase * unidad de compilación * o * unidad de traducción *. –

+3

y +1 para señalar que los espacios de nombres anónimos reemplazan el modificador 'static' para las variables globales. –

12

Una variable estática superiores declarada en un archivo de cabecera fuera de la clase sería file-scoped en cada archivo .c que incluye el encabezado. Eso significa que se puede acceder a una copia separada de una variable con el mismo nombre en cada uno de los archivos .c donde se incluye el archivo de encabezado.

Una variable de clase estática por el contrario es class-scoped y la misma variable estática está disponible para cada unidad de compilación que incluye el encabezado que contiene la clase con variable estática.