34

My project consists of only two source files:

a.cpp:

const int n = 8;

b.cpp:

extern const int n;

int main()
{
    // error LNK2001: unresolved external symbol "int const n" (?n@@3HB)
    int m = n; 
}

I know there are several methods to make it work; however, I just wonder WHY it does't work?

xmllmx
  • 39,765
  • 26
  • 162
  • 323

5 Answers5

59

It's because const implies internal linkage by default, so your "definition" isn't visible outside of the translation unit where it appears.

In this case, by far the best solution is to put the declaration (extern int const n;) in a header file, and include that in both a.cpp and b.cpp. The linkage is determined by the first declaration the compiler sees, so the later definition in a.cpp will have the correct (external) linkage.

Alternatively, you can force the linkage in the definition:

extern int const n = 8;

Despite the extern, this is still a definition; anything with an initializer outside of a class definition is a definition.

James Kanze
  • 150,581
  • 18
  • 184
  • 329
11

const and constexpr variables in C++ have internal linkage (and thus aren't accessible in other compilation unit) if they aren't also declared extern (either in the definition or in a previous declaration).

In C, it isn't the case (well C hasn't constexpr) so your code is valid, and more you can put extern on a definition.

So if you want to write code which is both C and C++ (and the two declarations should probably come from the same header as James pointed out):

// a.cpp
extern const int n;
const int n = 8;

// b.cpp
extern const int n;

int main()
{

    int m = n; 
}

if you don't

// a.cpp
extern const int n = 8;

is also possible

AProgrammer
  • 51,233
  • 8
  • 91
  • 143
3

Declare it extern in a.cpp and just use without extern in b.cpp:

a.h

extern const int n ;

a.cpp

#include "a.h"
...
const int n= 8

b.cpp:

#include "a.h"
...


int main()
{        
    int m = n; 
}
Gjordis
  • 2,540
  • 1
  • 22
  • 32
  • Hmm, used to do this with a header file. Including the header with the extern is the simplest way. – Gjordis Feb 15 '13 at 12:33
  • 1
    Actually, you should *remove* `const int n;` from b.cpp. The included header is whats needed. – Roddy Feb 15 '13 at 12:39
2

To share a const object among multiple files, you must define the variable as extern.

To define a single instance of a const variable, we use the keyword extern on both its definition and declaration(s):

From these rules you just need to add the extern keyword in your definition. you already have it in declaration.

Arpit
  • 12,767
  • 3
  • 27
  • 40
1

If the other answers here do not do the trick, it may be the case that you have your definitions in different namespaces... if the compilation passes, and you get an undefined symbol linker error:

  • check the namespace of the undefined symbol; that's the effective namespace for the extern const int n declaration.
  • ensure that's your effective namespace where you make the const int n = 8 definition.
einpoklum
  • 118,144
  • 57
  • 340
  • 684