Как правильно использовать extern для глобальных переменных? - PullRequest
2 голосов
/ 05 июля 2011

файл a.cc

int a = 0;

файл b.cc

#include "a.cc"

файл main.cc

#include "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

Что я здесь не так делаю?

Ответы [ 4 ]

5 голосов
/ 05 июля 2011

Вы включаете .cc (или .cpp) файлы, что неправильно. Не делай этого. Вам нужен заголовок, и в этом положить 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
}
1 голос
/ 05 июля 2011

Вы делаете именно то, что сказал компоновщик: вы предоставляете несколько определений «а». И a.cc, и b.cc определяют переменную 'a' как нечто с внешней связью.

Не делай этого!

Не включать исходный файл. Есть моменты, когда вы действительно хотите это сделать, но, опять же, бывают случаи, когда вы хотите использовать goto.

0 голосов
/ 05 июля 2011

При использовании include представьте, что все файлы объединены в один файл. Это в основном то, что видит компилятор, потому что все было включено препроцессором до стадии компиляции.

Итак, ваш main.cc начинает выглядеть так.

int a;
extern int a;

Компилятор считает, что это нормально, потому что extern без инициализатора - это просто объявление, поэтому для него не выделяется память. «int a», однако, является определением, поэтому main.o включает в себя инструкции по выделению памяти для.

Как только вы связываете его, компоновщик замечает, что a.o и b.o уже определили также "a". «a», потому что это то место, где оно было первоначально определено, и «b», потому что b включает «a», которое имело определение.

Чтобы это исправить, просто уберите #include "b.cc" в main.cc. На самом деле, вынимайте b.cc целиком, потому что в этом нет никакого смысла.

Если вы действительно хотите сделать это правильно, создайте отдельный заголовок для «a» с именем a.h с помощью extern int a. Тогда main.cc и b.cc могут свободно включать a.h без переопределения a.

0 голосов
/ 05 июля 2011

Именно то, что говорит вам компилятор - вы в итоге определяете a во всех трех единицах перевода!Вы хотите наоборот: многократно включенное объявление 1005 * должно быть внешним, и должно быть только определение одно .Например:

// 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
}
...