Reputation: 51
IDE:codeblocks 13.12
--------------main.cpp------------------
#include<iostream>
using namespace std;
extern const int x;
int main()
{
cout << x << endl;
}
--------------sub.cpp-------------------
extern const int x = 10;
when I try to run the code before , the compiler show the error :
E:\NewProject\Test\main.cpp|8|undefined reference to `x'|
so, who can tell me how to solve this problem? (I have tried create a head file just like:
extern const int x;
and let both cpp file include this head file. but it make no use)
and if I want create a array at main.cpp just like:
int _array[x];
what should I do?
I'm new here, and not good at English. Thanks very much!!
Upvotes: 2
Views: 211
Reputation: 21721
The extern
keyword is saying: This is a declaration only.
For a variable, you need exactly one definition, ie. a declaration without extern
somewhere else:
// foo.h
extern int i;
// foo.cc
#include "foo.h"
int i; // definition
// bar.cc
#include "foo.h"
int main () {
++i; // modifies global variable
}
Special Rules for const
A common use case for const
variables is that you define constants in a header file and then use them everywhere else in your program:
// my_constants.h
const int NumHoursInDay = 24;
const int NumMinutesInHour = 60;
If these variables were not const
, then including my_constants.h
into different translation units (source files + their headers) would result in a linker error due to having multiple definitions of the variables.
The standard committee decided that this was going to be a common enough use case that they actually put a special rule for variables declared const
, C++ '03 7.1.5/2:
An object declared in namespace scope with a const-qualified type has internal linkage unless it is explicitly declared extern or unless it was previously declared to have external linkage.
This means that each translation unit will have it's own private copy of the const
variable. The linker won't try to merge them together and so there won't be an error.
So the first point is that you can actually just remove extern
from your exmaples and your code will compile and link correctly, all because of this special behavior of const
.
However, for whatever reason, if you decided you do want to declare your variable first and then have a single definition in the project, you may already have noticed that the following will still generate a linker error:
// foo.h
extern const int i;
// foo.cc
const int i = 0;
This is because the linker expects to find a definition for the i
in foo.h and as the i
in foo.cc has internal linkage (ie. it is invisible outside of that translation unit) the linker won't consider these objects to be the same.
This can be addressed by looking at the end of the quote from the standard:
or unless it was previously declared to have external linkage.
What we need to do is to tell the compiler that i
in foo.cc should have external linkage by first declaring it with extern
and then defining it without extern
.
// foo.cc
extern const int i;
const int i = 0;
And the best way to do this is to include our header file so that we only have the one declaration:
// foo.cc
#include "foo.h" // contains the extern declaration of 'i'
const int i = 0;
Array Dimension
One final point is that an array dimension needs to be a constant expression. Adding to the confusion here, an extern const
variable that is not defined in the current translation unit is not considered to be a constant expression:
extern const int ArrayDim;
int array[ArrayDim]; // Illegal C++
The code may compile, especially if you're using g++, as there is a C language feature called Variable Length Arrays. Behind the scenes the compiler is hiding memory allocations to support this.
As you intend to use your constant across multiple translation units and you need it to be used as a constant expression then the best option is to define your constant in a header file:
// my_constants.h
const int x = 10;
#include<iostream>
#include "my_constants.h"
using namespace std;
int main()
{
int _array[x];
cout << x << endl;
}
Upvotes: 4
Reputation: 1322
extern
means that your variable is just declared here but defined in another translation unit. So you can have many declaration of your constant extern const int x;
but you must have exactly one definition of this constant const int x = 10;
Upvotes: 3