2010-05-15 18 views
6
... 
#include "test1.h" 

int main(..) 
{ 
    count << aaa <<endl; 
} 

aaa se define en test1.h y no hice uso de la palabra clave extern, pero todavía se puede hacer referencia a aaa.¿Es realmente necesaria la palabra clave extern?

Así que dudo que extern realmente necesario?

+0

También debe proporcionar el contenido de test1.h. Es posible que use la terminología incorrecta para describir lo que está en test1.h. – sellibitze

Respuesta

1

Si aaa no está definido en otra unidad de compilación, no necesita extern, de lo contrario lo hace.

5

Si su test1.h tiene la definición de aaa y desea incluir el archivo de encabezado en más de una unidad de traducción, se encontrará con un error de definición múltiple, a menos que aaa sea constante. Mejor defina el aaa en un archivo cpp y agregue la definición extern en el archivo de encabezado que podría agregarse a otros archivos como encabezado.

regla de oro para tener variable y constante en el archivo de cabecera

extern int a ;//Data declarations 
const float pi = 3.141593 ;//Constant definitions 

Desde constante tienen vinculación interna en C++ cualquier constante que se define en una unidad de traducción no serán visibles a otra unidad de traducción, pero no es el caso de la variable tienen un enlace externo, es decir, son visibles para otra unidad de traducción. Poner la definición de una variable en un encabezado, que se comparte en otra unidad de traducción daría lugar a una definición múltiple de una variable, lo que llevaría a un error de definición múltiple.

3

En ese caso, extern no es necesario. Extern es necesario cuando el símbolo se declara en otra unidad de compilación.

Cuando utiliza la directiva de preprocesamiento #include, el archivo incluido se copia en lugar de la directiva. En este caso, no necesita extern porque el compilador ya conoce aaa.

+0

¿Cómo se define ** unidad de compilación **? – httpinterpret

+2

@httpinterpret cada archivo cpp junto con todos los encabezados incluidos formarán unidades de compilación/traducción, cppfile == unidad de compilación. Los archivos de encabezado son solo un mecanismo para reducir el tipeo, mire su proyecto como un grupo de archivos cpp con "header.h" reemplazado por el contenido real del archivo de encabezado. La unidad de compilación es solo archivos de objeto que se ven después de la compilación, vincular todos esos archivos le dará el exe/dll. – yesraaj

7

que he encontrado la mejor manera de organizar sus datos es seguir dos reglas simples:

  • declaran Sólo las cosas en los archivos de cabecera.
  • Defina cosas en C (o cpp, pero voy a utilizar C aquí para simplificar) los archivos.

Por declarar, me refiero a notificar al compilador que existen cosas, pero no asignarles almacenamiento. Esto incluye typedef, struct, extern y más.

Por definición, I generalmente significa "asignar espacio para", como int y así sucesivamente.

Si usted tiene una línea como:

int aaa; 

en un fichero de cabecera, cada unidad compilación (básicamente define como un flujo de entrada al compilador - el archivo C junto con todo lo que trae con #include , recursivamente) obtendrá su propia copia. Eso causará problemas si vincula dos archivos de objeto que tienen el mismo símbolo definido (excepto bajo ciertas circunstancias limitadas como const).

Una mejor manera de hacer esto es definir que aaa variable en uno de sus archivos C y luego poner:

extern int aaa; 

en el archivo de cabecera.

Tenga en cuenta que si su archivo de encabezado solo está incluido en un archivo C, esto no es un problema. Pero, en ese caso, probablemente ni siquiera tenga un archivo de cabecera. Los archivos de encabezado son, en mi opinión, solo para compartir cosas entre unidades de compilación.

+0

¿Puedes elaborar el caso que mencionaste que "si unes dos archivos de objetos juntos que tienen el mismo símbolo definido"? ¿Cómo puede 'const' arreglar el problema? - – httpinterpret

+0

'extern int aaa;' no es una definición. es una declaración. Además, 'struct foo {int j};' es una definición que obviamente está bien en los archivos de encabezado. Vale la pena utilizar la terminología correcta y haber leído la regla de una definición. – sellibitze

+0

@sellibitze, soy consciente de esta diferencia. Me estoy preguntando por qué 'const' puede solucionar el problema mencionado por @paxdiablo – httpinterpret

12

extern tiene sus usos. Pero principalmente involucra "variables globales" que son mal vistas. La idea principal detrás de extern es declarar cosas con enlaces externos. Como tal, es todo lo contrario de static. Pero el enlace externo es en muchos casos el enlace predeterminado, por lo que no necesita extern en esos casos. Otro uso de extern es: puede convertir las definiciones en declaraciones. Ejemplos:

extern int i; // Declaration of i with external linkage 
       // (only tells the compiler about the existence of i) 

int i;   // Definition of i with external linkage 
       // (actually reserves memory, should not be in a header file) 

const int f = 3; // Definition of f with internal linkage (due to const) 
       // (This applies to C++ only, not C. In C f would have 
       // external linkage.) In C++ it's perfectly fine to put 
       // somethibng like this into a header file. 

extern const int g; // Declaration of g with external linkage 
        // could be placed into a header file 

extern const int g = 3; // Definition of g with external linkage 
         // Not supposed to be in a header file 

static int t; // Definition of t with internal linkage. 
       // may appear anywhere. Every translation unit that 
       // has a line like this has its very own t object. 

Mire, es bastante complicado. Hay dos conceptos ortogonales: Vinculación (externa vs interna) y la cuestión de la declaración frente a la definición. La palabra clave extern puede afectar a ambos. Con respecto a la vinculación, es lo opuesto a static. Pero el significado de static también está sobrecargado y, dependiendo del contexto, controla o no el enlace. La otra cosa que hace es controlar la vida útil de los objetos ("tiempo de vida estático"). Pero en el ámbito global, todas las variables ya tienen una vida útil estática y algunas personas pensaron que sería una buena idea reciclar la palabra clave para controlar la vinculación (esto es solo que estoy adivinando).

La vinculación básicamente es una propiedad de un objeto o función declarada/definida en "scope de espacio de nombre". Si tiene un enlace interno, no será accesible directamente por nombre desde otras unidades de traducción. Si tiene un enlace externo, solo habrá una definición en todas las unidades de traducción (con excepciones, vea una regla de definición).

+1

¿Hay alguna razón para usar 'extern const int g;', en lugar de simplemente 'const'? – Casebash

+1

@Casebash: si desea declarar una constante en un encabezado pero establecer su valor solo en algún archivo cpp, debe usar extern const. – sellibitze

Cuestiones relacionadas