There are two things going on here.
When you include a file, the included file is pasted into the including file before the compiler begins compiling. This means there is a complete copy of file.cpp in main.cpp that will be compiled.
Next, Visual Studio wants to compile cpp files. It sees file.cpp is part of the project, compiles it, and links it with the compiled output of main.cpp to make an executable program.
The linker now has to deal with two files (probably link.obj and main.obj) that have their own int i
. The linker gives up and prints out a multiple definition error message. It doesn't even try to figure out which one is correct because only the intentions of the programmer makes one more correct than the other. You will have to wait for telepathic compiler support in a future C++ standard to sort that mess out. Until then don't do it.
Note what I wrote earlier about the included file being copied into the including. This means even with int i
being defined in file.h you aren't out of trouble.
If main.cpp and future.cpp both include file.h, you once again have two files with int i
. Include guards will not help here because they only stop a header from being duplicated within one compiled file (a translation unit).
The solution to this is don't define identifiers in headers unless you take steps to make them unique or tell the compiler that it's OK that they aren't. Strongly prefer not defining the identifier to the alternatives.
For an identifier that is a variable use the extern
keyword to inform the compiler that i
, or any other variable exists, but will be allocated elsewhere. You are then required to define the variable in exactly one elsewhere. eg:
file.h
extern int i;
file.cpp
int i = 0;
Now main.cpp or any other file can include file.h and use i
. All of them are using the same i
, so be careful with it. Be very, very careful. There is very often a better way to share a variable across multiple translation units, so spend the time looking for a different solution. You will most likely thank yourself when debugging time comes.
An alternative is to define the variable as static
file.h
static int i;
When using static
every file that includes file .h has it's own i
that is only visible within the including file. The linker is no longer involved. This is also almost always a bad idea. If you have variables that must be defined to support a header file, odds are good what the header really needs is a class.
For an identifier that is a function, use the inline
keyword.