2012-04-06 20 views
51

Ho 2 file, A.cpp e B.cpp, in un'applicazione console Win32.errore LNK2005, già definito?

Entrambi i 2 file contengono solo le seguenti 2 righe di codice:

#include "stdafx.h" 
int k; 

Quando si compila produce l'errore

Error 1 error LNK2005: "int k" ([email protected]@3HA) already defined in A.obj 

Non capisco cosa sta succedendo.

Qualcuno può spiegarmi questo per favore?

+7

T & T Group? È il nome della tua azienda? Non consiglierei di firmare con il nome della tua azienda quando farai le domande di base. Soprattutto se i tuoi clienti si aspettano che tu protegga le loro informazioni di qualche tipo. – CodyBugstein

+1

** Suggerimento per gli amici: ** manca '#include" stdafx.h "' è anche la fonte di questo errore. – Bitterblue

risposta

77

Perché questo errore?

Si è rotto il one definition rule e quindi l'errore di collegamento.

Soluzioni suggerite:


Se è necessario lo stesso variabile denominata nei due file cpp allora avete bisogno di usare namespace Nameless (Anonimo Namespace) per evitare l'errore.

namespace 
{ 
    int k; 
} 

Se è necessario condividere la stessa variabile in più file, allora è necessario utilizzare extern.

A.h

extern int k; 

A.cpp

#include "A.h" 
int k = 0; 

B.cpp

#include "A.h" 

//Use `k` anywhere in the file 
+2

In caso di 'extern',' k' dovrebbe essere definito una volta in uno qualsiasi dei file sorgente. – Mahesh

+1

@Mahesh: Ma ovviamente :) –

+0

Ho anche questo problema ma non lo sto ridefinendo, sto provando a usare il mio .dll in un altro progetto .dll per creare un wrapper gestito per esso. Qualche consiglio? Le variabili statiche –

6

si Supponendo che vuole 'k' per essere un diverso ent valore in diversi file cpp (da qui dichiara due volte), provare a cambiare entrambi i file

namespace { 
    int k; 
} 

Ciò garantisce che il nome di 'k' identifica univocamente 'k' attraverso unità di traduzione. La vecchia versione static int k; è obsoleta.

Se si desidera che puntino allo stesso valore, modificare uno su extern int k;.

1

E se si desidera che queste unità di traduzione condividano questa variabile, definire int k; in A.cpp e inserire extern int k; in B.cpp.

13

Se si desidera sia per fare riferimento alla stessa variabile, uno di loro dovrebbe avere int k;, e l'altro dovrebbe avere extern int k;

Per questa situazione, in genere si mette la definizione (int k;) in un .cpp file e mettere la dichiarazione (extern int k;) in un'intestazione, da includere ovunque sia necessario accedere a tale variabile.

Se si desidera che ogni k essere una variabile indipendente che appena capita di avere lo stesso nome, è possibile contrassegnarli come static, come: static int k; (in tutti i file, o per lo meno tutti, ma un file). In alternativa, ci si può un namespace anonimo:

namespace { 
    int k; 
}; 

Anche in questo caso, in tutti, ma al massimo uno dei file.

In C, il compilatore in genere non è così schizzinoso su questo. In particolare, C ha un concetto di "definizione provvisoria", quindi se si ha qualcosa come int k; due volte (nello stesso file di origine o separato) ognuno sarà trattato come una definizione provvisoria, e non ci sarà un conflitto tra loro . Questo può essere un po 'confuso, tuttavia, perché non è ancora possibile avere due definizioni che includono entrambi gli inizializzatori: una definizione con un inizializzatore è sempre una definizione completa, non una definizione provvisoria. In altre parole, int k = 1; visualizzato due volte sarebbe un errore, ma int k; in un posto e int k = 1; in un altro no. In questo caso, lo int k; verrà trattato come una definizione provvisoria e lo int k = 1; come una definizione (e entrambi si riferiscono alla stessa variabile).

+0

+1 ma jerry, sarebbe bello se si aggiungessero alcune parole su C. penso che l'OP provenga da C, con le sue dichiarazioni "provvisorie" ... il C/La differenza di C++ mi ha confuso per un tempo di registrazione. –

+0

La parola chiave statica mi ha aiutato quando ho definito la variabile solo una volta. Grazie! – Pete

5

Entrambi i file definiscono la variabile k come numero intero (int).

Di conseguenza, il linker vede due variabili con lo stesso nome e non è sicuro quale deve essere utilizzato se si fa riferimento a k.

Per risolvere questo problema, modificare uno dei dichiarazioni:

extern int k; 

Ciò significa: "(. Cioè l'altro file). K è un intero, dichiarato qui, ma definito esternamente"

Ora c'è solo una variabile k, che può essere correttamente indicata da due file diversi.

+0

Puoi fare riferimento alla variabile in più di un altro luogo (cioè senza 'extern')? – CodyBugstein

1

Il linker indica che è stata definita la variabile k più volte. In effetti, hai una definizione in A.cpp e un'altra in B.cpp. Entrambe le unità di compilazione producono un file oggetto corrispondente che il linker utilizza per creare il tuo programma. Il problema è che nel tuo caso il linker non conosce la definizione di k da utilizzare. In C++ puoi avere solo una definizione dello stesso costrutto (variabile, tipo, funzione).

Per risolvere il problema, si dovrà decidere che cosa il vostro obiettivo è

  • Se si desidera avere due variabili, entrambe di nome k, è possibile utilizzare un dominio anonima in entrambi.file cpp, quindi fare riferimento a k come si fa ora:

.

namespace { 
    int k; 
} 
  • È possibile rinominare uno dei k s a qualcos'altro, evitando così il defintion duplicato.
  • Se si desidera avere una sola definizione di k e utilizzarlo in entrambi i file .cpp, è necessario dichiararlo in uno come extern int k; e lasciarlo così come è nell'altro. Questo dirà al linker di usare l'unica definizione (la versione invariata) in entrambi i casi - extern implica che la variabile sia definita in un'altra unità di compilazione.
57

add/FORCE: MULTIPLE alle opzioni della riga di comando del linker.

Da MSDN: "Usa/FORZA: MULTIPLE per creare un file di output indipendentemente dal fatto che LINK trovi più di una definizione per un simbolo."

+4

Questa è la ** sola ** soluzione quando il linker o il preprocessore non riesce a vedere che quella cosa è definita solo ** una volta **! Deve essere anche un bug in VS. Mi chiedo solo come ha funzionato per così tanto tempo per così tante persone. (Non mi riferisco alla Q qui, ma ai miei errori di linker che provengono da uno spazio esterno, immagino ...) – Bitterblue

+3

Ho la sensazione che questo sia un modo 'brute-force' per farlo e in realtà non risolvere il problema originale; ha fatto metà delle mie funzioni puntare a zero. Dato che questo ha risolto il mio problema, sto dando questa risposta +1. – cybermonkey

+1

Desideriamo sottolineare che questo potrebbe essere l'unico modo per risolverlo se compilate con il nuovo compilatore il codebase che usa vecchie librerie statiche compilate. – Predelnik

Problemi correlati