What is the correct way of using extern for global variables?
file a.cc
int a = 0;
file b.cc
#include "a.cc"
file main.cc
#incl开发者_如何转开发ude "b.cc"
extern int a;
int main() {
}
g++ -c a.cc
g++ -c b.cc
g++ main.cc a.o b.o
error: multiple definitions of a
What am I doing wrong here?
You include a .cc
(or .cpp
) files, which is wrong. Do not do that. You need a header, and in that put the extern int a;
:
// a.h
// include guards omitted
extern int a;
// a.cc
#include "a.h"
int a;
// b.cc
#include "a.h"
// main.cc
#include "a.h"
int main(){
// use a
}
You are doing exactly what the linker said: You are providing multiple definitions of 'a'. Both a.cc and b.cc are defining the variable 'a' as something with external linkage.
Don't do that!
Don't #include a source file. There are times when you do want to do that, but then again, there are times when you want to use goto
.
Exactly what the compiler tells you -- you end up defining a
in all three translation units! You want it the other way around: The repeatedly included declaration should be extern, and there must only be one definition. For instance:
// header: stuff.h
extern int a;
void foo();
// first TU: a.cpp
#include "stuff.h"
void foo() { a += 1; }
// second TU: main.cpp
#include "stuff.h"
int a; // `a` is stored in this TU
int main() {
a = 6;
foo();
// now a == 7
}
When using the include, imagine placing all the files into one file. That is basically what the compiler sees because everything was included by the preprocessor before the compiler stage.
So your main.cc starts looking like this.
int a;
extern int a;
The compiler considers this okay because extern without an initializer is just a declaration so memory is not allocated for it. "int a" is a definition, however, so main.o includes instructions for allocating memory for a.
Once you link it, the linker notices that a.o and b.o already has "a" defined as well. "a" because this is where it was originally defined and "b" because b included "a" which had the definition.
To fix this, just take out #include "b.cc" in main.cc. In fact, take out b.cc entirely because there is no point in it.
If you really want to do this right, create a separate header for "a" called a.h with extern int a. Then main.cc and b.cc are free to include a.h without redefining a.
精彩评论