A: В С++ есть такое правило - «правило одного определения» (One Definition Rule). Оно (среди прочего) требует: 1. В одной единице трансляции (для простоты - одном cpp-файле) должно быть только одно определение определенного класса/функции/перечисления. Т. е. следующий исходный текст будет считаться некорректным:
// main.cpp struct A { int x; int y; }; struct A { int x; int y; int z; };
Потому что в нем два определения класса A, что нарушает правило одного определения.
2. Если в разных единицах трансляции (cpp-файлах) определны одноименные классы/функции/перечисления, и они представляют одну и туже сущность, то их определения должны быть идентичны (определение этой идентичности можно найти в стандарте). Т. е. следующий пример будет некорректным:
// file1.cpp struct A { int x; int y; }; void foo1(const A& a) { std::cout << a.x << " " << a.y << std::endl; } // file2.cpp struct A { int z; int y; int x; }; void main() { A a = {1, 2, 3}; foo1(a); }
Потому что в файлах file1.cpp и file2.cpp определения класса A не совпадают. Так вот, для того, чтобы не перечислять всякий раз во всех файлах проекта одни и теже функции/классы (с возможностью допустить при этом ошибку), все эти определения выносят в заголовочные файлы, после чего эти файлы включают в каждую единицу трансляции, где требуются необходимые определения. При этом в заголовочные файлы вносят т. н. охранные макроопределения:
// file.h #ifndef file_h__ #define file_h__ // здесь идет перечисление необходимых определений #endif
Необходимо это для того, чтобы исключить повторную обработку содержимого заголовочного файла в случаях, подобных такому:
// common.h class A {}; // file1.h #include "common.h" class B : public A { } //file2.h #include "common.h" class C : public A { }; // main.cpp #include "file1.h" #include "file2.h"
Компиляция main.cpp завершится ошибкой, т. к. в нем будут присутствовать два определения класса А (включенные через file1.h и file2.h). В случае использования охранных макросов:
// common.h #ifndef common_h__ #define common_h__ class A {}; #endif
при обработке файла file2.h компилятор (точнее, препроцессор) увидит, что макроопределение common_h__ уже определено, условие выполнено не будет, и текст файла не будет включен (повторно) в main.cpp.