Это не обязательно. Но при циклических зависимостях и проектах с большим количеством исходных файлов или библиотек оно нужно.
Объявление переменной в заголовках с приставкой extern
означает, что переменная известна и она находится где-то.
h.h :
extern int glob ;
a.cpp :
# include "h.h"
...
++ glob ;
...
b.cpp :
# include "h.h"
int glob = 0 ;
Без предварительного объявления в a.cpp
произойдёт ошибка неизвестной переменной с неизвестным типом.
Предварительное объявление функции уже надо при задаче, использующей рекурсию.
funA(x) := funA(x/2) + funB(x/2) или 0
funB(x) := funA(x/2) - funB(x/2) или 0
Без предварительного объявления эти функции не скомпилируются.
int funB ( int ) ; // надо
int funA ( int x ) {
if ( x )
return funA ( x / 2 ) + funB ( x / 2 ) ;
return 0 ;
}
int funB ( int x ) {
if ( x )
return funA ( x / 2 ) - funB ( x / 2 ) ;
return 0 ;
}
А если они находятся в разных .cpp
файлах то обе эти функции надо предварительно объявлять, так как один файл должен знать о существовании другого.
Предварительное объявление структуры уже надо, чтобы компилятор знал о её размере в байтах. И при сборке например массива структур можно было выделить для них чёткое место в памяти.
struct S ; // предварительное объявление только типа
struct S Arr [ 2 ] ; // ошибка - неизвестен размер
struct S {
double d ;
float f ;
} ;
Ну и точно так-же если разные переменные находятся в разных .cpp
файлах то обе эти переменные должны знать о размере структуры и её надо полностью объявлять в заголовочном файле.