Если #включено, оно переопределяется. Если нет, он не объявлен

#c #linker #g

#c #компоновщик #g

Вопрос:

Это довольно длинный код, но в двух словах, у меня есть main.hpp, a main.cpp , io.ГЭС и io.cpp .

Оба main.cpp и io.cpp включите main.hpp для использования объявленных там переменных, а io.hpp включает только стандартный код:

main.hpp

 #ifndef MAIN_HPP
#define MAIN_HPP

#include <somestandardstuffhere>

int counter;

#endif // MAIN_HPP
 

main.cpp

 #include "main.hpp"
#include "io.hpp"

int main(){
    doStuffWithCounter();
    return 0;
}
 

io.hpp

 #ifndef IO_HPP
#define IO_HPP

#include <usedstandardstuff> // Some of the headers included here are included in main.hpp

void doStuffWithCounter();

#endif //IO_HPP
 

io.cpp

 #include "main.hpp"
#include "io.hpp"

void doStuffWithCounter(){
    counter = 1;
}
 

Если это хороший минимальный код, при компиляции вы должны получить сообщение об ошибке компоновщика, в котором говорится, что counter переопределяется в его собственной строке, но, если я избавлюсь, например, io.cpp от ‘s #include "main.hpp" , переменная не будет доступна для использования в ее коде.

Я компилирую, используя только исходные файлы: g -std=c 11 io.cpp main.cpp .

Как бы вы это исправили? Почему недостаточно #ifndef ing, чтобы предотвратить возникновение этих ошибок?

Комментарии:

1. На самом деле это не ответ, но если вы не используете «стандартные» включения в файле заголовка, вам не следует добавлять их туда. Это приведет к тому, что они будут включены везде, где включен заголовок, что приведет к замедлению компиляции и, возможно, вызовет проблемы с пространством имен.

2. int counter; не должно быть в заголовочном файле, поскольку оно определяет и объявляет counter . Вместо этого в заголовочном файле должно быть extern int counter; , который просто объявляет его, не определяя его.

3. @Eljay если я это сделаю, он сообщит мне, что переменная не объявлена io.cpp .

4. Добавьте это io.cpp в начало после всех #include директив: int counter;