В h файлах не выделяется память. То есть выделять можно, но это нехорошо.
В h файлах по возможности не описывается реализация функций и методов. То есть описывать можно, но это нехорошо (разрешено только для inline-функций).
Потому, что дважды включённый заголовник создаст конфликт - попытка дважды выделить память под переменную, дважды реализовать код функции. Сами смотрите - math.h вы можете включить во все c/cpp, которым нужен косинус.
Это значит:
1) в заголовниках не создаются никакие переменные.
2) в заголовниках не кодируются функции.
Остаётся:
1) в заголовниках упоминаются переменные через слово extern
2) в заголовниках упоминаются функции через слово extern.
3) в заголовниках могут описываться классы и в них упоминания методов. extern не обязателен.
Следовательно:
Компилируемая часть проекта, содержащая коды и выделение память под переменные (то есть тупо c/cpp), включается посредством главного файла описывающего проект как таковой. В вашем случае, если я не сильно вру, это bdsproj.
Некомпилируемая (условно назовём так) часть проекта, содержащая упоминания, может не включаться в проект, а вставляться в c/cpp посредством директивы #include.
Итого: заголовники включают только информацию как обращаться с переменной (константой, перечислением), функцией(методом), классом(структурой). Реализует это всё ровно один файл проекта, который тематически с этим связан (косинус реализуется только в math.c). Поэтому любой или все c/cpp вашего проекта может включить заголовник math.h, чтобы знать, как полагается вызывать косинус или ваш собственный класс.
P.S. А вообще, директива #include просто копипастит текст того файла в этот. Вы можете вообще озорным образом извращаться с этой директивой - начать код в одном файле, вставить продолжение из второго, а скобочку закрыть в третьем. И называться они могут superfun.c, superfun22.continuation, fun22super.closingparenthesis. Но зачем? Есть культурные договорённости как грамотно использовать директиву #include.