Why is it a linker error to # include this file more than once?

This question is not so much a "how to solve" question, but rather a question about why this does not work?

In C ++, I can define a bunch of variables that I want to use for multiple files in several ways.

I can do it like this:

int superGlobal; #include "filethatUsesSuperglobal1.h" int main() { // go. } 

This method ONLY works if "filethatUsesSuperglobal1.h" has all its implementation there in the header and without an attached .cpp file.

Another way (the "more correct" way) is to use extern:

externvardef.h

 #ifndef externvardef_h #define externvardef_h // Defines globals used across multiple files. // The only way this works is if these are declared // as "extern" variables extern int superGlobal; #endif 

externvardef.cpp

 #include "externvardef.h" int superGlobal; 

filethatUsesSuperglobal1.h

 #include "externvardef.h" #include <stdio.h> void go(); 

filethatUsesSuperglobal1.cpp

 #include "filethatUsesSuperglobal1.h" void go() { printf("%d\n", superGlobal ); } 

main.cpp

 #include <stdio.h> #include "externvardef.h" #include "filethatUsesSuperglobal1.h" int main() { printf( "%d\n", superGlobal ) ; go() ; } 

This is a small point and a somewhat insignificant question, but Why do I need to declare it extern - should #include be protected on "externvardef.h" to avoid overriding?

This is a linker error, although there is #include protection around it in this header file. So this is not a compiler error, its a linker error, but why.

+4
source share
5 answers

Think, in terms of code - there is this superGlobal character that points to an integer.

You have many .o files to combine them into one executable file. Each of the .o files has its own superGlobal character. Which one should the linker use?

The extern declaration says: the other of the compilation units (.o files) is going to declare this symbol, so I can use it. Thus, there is only one copy, so the linker knows what to do.

+16
source

#ifndef defender works only for each file. Therefore, if you leave extern off, you will get superGlobal defined 3 times, once when compiling each of the main.cpp, filethatUsesSuperglobal1.cpp and externvardef.cpp files.

+5
source

should #include be protected on "externvardef.h" to avoid overriding?

Included guards protect against multiple declarations in a single compilation unit; if an extern declaration is required to prevent multiple definitions in one executable module.

Please note that it is important to distinguish between declaration and definition. You will see this difference in the generated error messages. Turn on guards incorrectly, and you will receive several declaration errors from the compiler. Wrong external code, and you get some definition errors from the linker. Also note the role of the compiler and linker in this.

+4
source

You are breaking a Single Definition Rule (ODR). This variable can only be defined once.

When the title says β€œint SuperGlobal;”, each file containing the title defines a variable. When the title says "extern int SuperGlobal;", a variable is declared (so various files know how to access it), but it will be defined only once - in the corresponding source file.

+2
source

#Ifndef protections prevent the display of the header more than once per cpp file . After the compiler finishes processing one cpp file, it will start from the next, discarding all knowledge of what happened when the previous file was compiled. Each cpp file creates an object file, each of which has its own copy of the global variable. When the linker tries to bind everything together, it finds several definitions of where in the memory a global variable can be found. The linker has no way of knowing which object file to respect and which to ignore. Some linkers will simply pick one up and ignore all the others, others will be clogged. In any case, this is a mistake.

+2
source

All Articles