问题
head.h
#pragma once
namespace foo
{
int bar;
int funct1();
}
head.cpp
#include "head.h"
int foo::funct1()
{
return bar;
}
main.cpp
#include <iostream>
#include "head.h"
int main()
{
foo::bar = 1;
std::cout << foo::funct1() << std::endl;
return 0;
}
Error LNK2005 "int foo::bar" (?bar@foo@@3HA) already defined in head.obj
I don't understand what is going on. I tried looking for the answer but everyone's questions are so specific to their code and don't even look close to the problem that I am having.
I am not including .cpp files into main. I am not redefining anything. I am literally just assigning 1 to the variable then returning it with a function in the same namespace. How is it being defined multiple times?
回答1:
The header head.h
is included in two compilation units head.cpp
and main.cpp
. So the variable bar
is defined twice. You could declare the variable without its definition the following way
#pragma once
namespace foo
{
extern int bar;
int funct1();
}
and then define it in some cpp module.
回答2:
This foo
namespace-level bar
declaration:
namespace foo
{
int bar;
}
is actually a definition.
To make it a declaration, mark the bar
as extern
in head.h:
namespace foo
{
extern int bar;
}
Then define it in head.cpp:
int foo::bar = 0;
回答3:
head.h
is included in both main.cpp and head.cpp.
So the variable is defined twice.
Possible Solution: make it inline. The "extern" solutions are also good, although older in approach.
namespace foo
{
inline int bar;
}
回答4:
How is it being defined multiple times?
It is defined once in head.cpp and once in main.cpp. That is a total of two times. This violates the one definition rule, which states that there may only be one definition for every variable.
int bar;
This is a definition of a variable. You've included it into two translation units.
A variable can be declared without definition in an extern declaration:
extern int bar;
Replace the definition with such declaration, and put the definition into exactly one translation unit.
回答5:
I am not redefining anything. I am literally just assigning 1 to the variable
You're redefining the variable!
head.cpp
has one via #include "head.h"
, and main.cpp
has one via #include "head.h"
.
You need to merely declare it (unusual but not too strange) in the header:
extern int bar;
…then define it in one translation unit. This is just like what you do with static
class members (albeit with slightly different syntax).
Since C++17, you may do this by instead plopping the inline keyword on to your definition.
Alternatively, avoid mutable globals…
回答6:
Do carefully note that foo
is not a class, but a namespace. When you declare a free variable in the header file:
int bar;
And then #include this header file multiple times (into different CPP files, causing multiple translation unit compilations), you'd get a linker error. Everyone knows it.
And, you'd add extern
attribute at the declaration, and define the variable elsewhere in one of the CPP/C file.
Putting a global variable into a namespace is nothing but giving the global variable a different name. Think if foo::bar
as foo__NS__bar
, and hence you must add extern
in the header and define foo::bar
at some locatoin.
Note that this is different from a non-static member variable of a class. A class variable doesn't need to be defined/declared this way since the class is a type. Each instantiated variable of class-type would have a separate copy of the variable.
Further to that, when you add a static
variable in the class, you are giving that logically global variable another name. Thence, you must have that static-variable defined one of the CPP file.
回答7:
The problem is you are defining foo::bar more than once: in header.h and in main.cpp. It's a global variable that's being defined more than once, and that's not possible. So the linker complains that you are defining it multiple times.
You can fix this by declaring foo::bar with extern:
namespace foo
{
extern int bar;
int funct1();
}
Then define it in header.cpp:
int foo::bar;
来源:https://stackoverflow.com/questions/56735173/variable-already-defined-in-obj-what-is-going-on-here