2009-10-02 12 views
5

El problema que tengo es básicamente el mismo que 'greentype' menciona en http://www.cplusplus.com/forum/beginner/12458/espacios de nombres con enlace externo

estoy compartiendo las variables a través de espacios de nombres y surge un problema cuando trato de poner mis definiciones de funciones en un archivo separado .

Considere el siguiente ejemplo, donde quiero pasar la variable 'i', que se define en el código principal, a la función a():


* nn.h: *

#ifndef _NN_H_ 
#define _NN_H_ 

namespace nn { 
int i; 
} 
#endif 

* * main.cpp

#include <iostream> 
#include "nn.h" 
using namespace std; 
using namespace nn; 

void a(); 

int main() 
{ 
i=5; 
a(); 
} 

void a() 
{ 
using namespace std; 
using namespace nn; 

i++; 
cout << "i = " << i << endl; 
} 

Pero ahora si pongo la definición de un() en un archivo separado ...


* * a.cpp

#include <iostream> 
#include "nn.h" 

void a() 
{ 
using namespace std; 
using namespace nn; 

i++; 
cout << "i = " << i << endl; 
} 

... entonces obtengo un error de "definición múltiple" al enlazar (g ++ main.cpp a.cpp -o main). Si hago la declaración 'i' en el archivo de encabezado 'extern' (como sugerido en otros foros), aparece un error de 'referencia no definida'. Puedo compilar cuando 'i' se declara como const en el encabezado, pero eso no es lo que quiero.

Cualquier sugerencia muy apreciada.

Respuesta

12

Cualquier objeto global, como i, debe tener exactamente una definición en algún lugar del programa, pero puede ser declarado varias veces.

El uso de extern sin un inicializador hace que una declaración sea solo una declaración. Esto es apropiado para su archivo de encabezado, pero aún debe definir i en algún lugar. Además de realizar la declaración del encabezado extern, también debe agregar una definición (es decir, una copia de la declaración sin extern) a uno y solo uno de sus archivos fuente.

Editar: Lea su pregunta, usted dice que quiere pasarle una variable a una función. Desde un punto de vista de estructura de código y estilo, esta no suele ser una buena razón para usar una variable compartida (global). En ausencia de razones imperiosas, normalmente debería definir una función que toma un parámetro y pasa un valor (posiblemente desde una variable local) desde el sitio llamante a esa función a través de su parámetro.

+0

Así que la única manera de hacerlo funcionar es hacer que 'i' sea global, es decir, ponga la definición 'namespace nn {int i = 5;}' en main.cpp, sobre int main() (y haga declaración 'extern'). Pero observe que en el ejemplo original (donde la función a() está en el MISMO ARCHIVO que main()), 'i' no era global - lo definí dentro de main(), y aun así pude compartirlo con, y modificar in, a() a través del espacio de nombres. Ese es el marco que necesito retener, porque realmente no puedo hacer que 'i' sea global, ya que (y otras variables que tengo y necesito compartir) se CALCULA en main() - No conozco sus valores de antemano . –

+0

No, no * definiste * it en 'main', simplemente lo usaste en' main'. La definición todavía estaba en 'nn.h' y todavía era una variable de ámbito de espacio de nombres (es decir, no una función local). Aún puede calcular valores y asignarlos a variables con ámbito de espacio de nombres en una función como main. Sin embargo, es mejor tener 'i' como una variable local en' main' y pasarlo (o una referencia) a 'a'. –

+0

@PetrH, para ser precisos, no era global porque estaba definido en 'nn', no porque estaba definido en' main' (como se ha dicho, simplemente es * used * allí). Para hacer que 'i' sea global, debe ponerlo * fuera * en cualquier espacio de nombres definido por el usuario. Ponlo por encima del espacio de nombres 'nn', por ejemplo. Actualmente, 'i' no es global, pero aún tiene un espacio de nombre con ámbito (no local). –

10

El archivo de cabecera debe decir:

namespace nn { 
    extern int i; 
} 

Ésta es una "declaración" no es una "definición".A continuación, desea una definición en uno y sólo un archivo:

namespace nn { 
    int i = 1; 
} 

Por supuesto, un enfoque mucho mejor es simplemente no tener variables globales en absoluto.

2

Esto no tiene nada que ver realmente con espacios de nombres, y todo tiene que ver con el enlace, externo o no, del símbolo i en sus diversos ejemplos. Por defecto, las variables globales tienen un enlace extern, mientras que los símbolos globales const tienen un enlace static; esto explica por qué funciona cuando se hace i const. Para resolver el problema, una forma de hacerlo es declarani con vinculación externo en el archivo de cabecera, a continuación, definen que sólo en uno de los archivos de implementación, como se muestra a continuación:

cabecera:

extern int i; 

ac:

int i: 

main.c:

int main() 
{ 
    i = 1; // or whatever 
} 

Tenga en cuenta que he eliminado el espacio de nombres para mayor claridad: el resultado final es el mismo.

Cuestiones relacionadas