Я знаю, что, должно быть, здесь что-то не так.
rank.h
#ifndef RANK_H
#define RANK_H
namespace mmi {
int chunk;
void rank(int my_rank);
}
#endif
rank.cpp
#include "rank.h"namespace mmi {
//do something with chunk
}
main.cpp
#include "rank.h"int main() {
mmi::chunk = 1;
}
И вывод компиляции;
g++ -g -Wall -std=gnu++11 -c -o main.o main.cpp
g++ -g -Wall -std=gnu++11 -c -o rank.o rank.cpp
mpic++ main.o rank.o -o main
rank.o:(.bss+0x0): multiple definition of `mmi::chunk'
main.o:(.bss+0x0): first defined here
collect2: error: ld returned 1 exit status
Makefile:12: recipe for target 'main' failed
make: *** [main] Error 1
Насколько я понимаю, заголовочный файл включается несколько раз. Но я ожидал исправить эту проблему с помощью #ifndef
,
Итак, могу я спросить, что здесь происходит?
Линия
int chunk;
это не только декларация, это также определение. Каждый файл .cpp, который #include
s .pp файл заканчивается определением его.
Измените это на
extern int chunk;
Затем убедитесь, что вы определили его в файле .cpp.
rank.cpp
#include "rank.h"namespace mmi {
int chunk;
//do something with chunk
}
В C ++ каждый файл (он же переводчик) компилируется по отдельности. Таким образом, компиляция main.cpp полностью независима от компиляции rank.cpp. Не существует способа, которым #define в одной компиляции может повлиять на другую компиляцию. И к тому времени, когда вы свяжете два ваших объектных файла вместе, определения исчезнут.
Цель включать охранников состоит в том, чтобы предотвратить включение одного заголовочного файла дважды во время одной компиляции, а не в нескольких компиляциях.