0

I'm trying to understand how exactly extern works in C++. There are many questions asked about this keyword on StackOverflow but none of them clarifies my problem:

Situation 1

AuxSource.cpp

int GlobalVar = 5;

Source.cpp

#include <iostream>
#include <conio.h>
#include "AuxSource.cpp"


int main()
{
    std::cout << GlobalVar;
    return 0;
}

ERROR: one or more multiply defined symbols found

ERROR: int GlobalVar already defined in AuxSource.obj

// What the heck!? I defined it once!

Situation 2

AuxSource.cpp

int GlobalVar = 5;

Source.cpp

#include <iostream>
#include <conio.h>
#include "AuxSource.cpp"

extern int GlobalVar; // added

int main()
{
    std::cout << GlobalVar;
    return 0;
}

ERROR: one or more multiply defined symbols found

ERROR: "int GlobalVar" already defined in AuxSource.obj

// Same errors.

Situation 3

AuxSource.cpp

int GlobalVar = 5;

Source.cpp

#include <iostream>
#include <conio.h>
// #include "AuxSource.cpp" - deleted

extern int GlobalVar;

int main()
{
    std::cout << GlobalVar;
    return 0;
}

// It works, but how is that possible?

Every tutorial out there uses the combination of including outer (non-main) file with some global variable and extern redeclaration + variable use in another module but it doesn't work for me. Either I still don't comprehend the concept of extern or something's wrong with my VS2013 (much less likely).

matt-pielat
  • 1,659
  • 3
  • 20
  • 33
  • It's explained here also I think: http://stackoverflow.com/questions/12573816/what-is-an-undefined-reference-unresolved-external-symbol-error-and-how-do-i-fix – πάντα ῥεῖ Jun 28 '14 at 21:22

3 Answers3

3

Your problem is this:

#include "AuxSource.cpp"

Normally, you do not include *.cpp files, but you include a corresponding *.h file. So you could have a header file AuxSource.h that contains:

extern int GlobalVar;

Then, you #include "AuxSource.h" in each of your source files, and so they each get an extern declaration of your global variable.

The actual definition of int GlobalVar = 5; would remain in AuxSource.cpp which is only compiled once.

Greg Hewgill
  • 951,095
  • 183
  • 1,149
  • 1,285
1

This isn't about extern more about linkage.

int GlobalVar = 5;

GlobalVar by default has external linkage. Try

const int GlobalVar = 5; //internal linkage

For more info see here.

Community
  • 1
  • 1
yizzlez
  • 8,757
  • 4
  • 29
  • 44
1

The include tells the compiler to include a copy of one file into another before compilation. And the linker only likes to have a symbol defined once. So this statement:

#include "AuxSource.cpp" 

causes GlobalVar to be defined twice: once in AuxSource.cpp, and a 2nd time in the file that is including AuxSource.cpp (Source.cpp). So both AuxSource.cpp and Source.cpp have this same code: int GlobalVar = 5;

That is why the linker tells you that the symbol GlobalVar is defined multiple times.

The usual pattern to use for having a global variable in one file that you need to use in another cpp file is to do this:

AuxSource.cpp:

int GlobalVar = 5;

AuxSource.h:

extern int GlobalVar;

Source.cpp:

#include <iostream>
#include <conio.h>
#include "AuxSource.h"

int main()
{
    std::cout << GlobalVar;
    return 0;
}

This way you can put #include "AuxSource.h" in many files and be able to use your one copy of GlobalVar that lives in AuxSource.cpp.

Bill Morgan
  • 538
  • 2
  • 14