Zdrojové a hlavičkové soubory v C a C++

06-Hlavičkové

Stavba programu

Platí, že v programu můžeme pracovat jen s tím, co překladač už zná. Nelze se odvolávat na funkci nebo na proměnnou, kterou jsme ještě nedeklarovali.
To se týká i datového proudu std::cout. (C++) Toto je, instance objektového typu; je uložena ve standardní knihovně. Abychom nemuseli její deklaraci opisovat do každého programu (a abychom nemuseli opisovat tisíce dalších deklarací knihovních funkcí, proměnných, operátorů, tříd atd.), máme v C/C++ k dispozici tzv. hlavičkové soubory.
Ty obsahují všechny informace, které překladač nezbytně potřebuje, aby mohl přeložit volání knihovní funkce, použití knihovního objektu apod. Standardní hlavičkové soubory v C++ jsou bez přípony, standardní hlavičkové soubory v jazyce C mají příponu .h. Pro uživatelem definované hlavičkové soubory se zpravidla používá přípona .h.
Informace o základních vstupních a výstupních proudech jazyka C++ jsou v hlavičkovém souboru iostream (ve starších překladačích se jmenoval iostream.h). Aby je měl překladač k dispozici, musíme tento soubor vložit do svého programu, a to před prvním použitím proudu std::cout — nejlépe hned na počátku zdrojového souboru. K tomu slouží direktiva #include, za kterou v lomených závorkách < a > následuje jméno souboru.

Umožňuje vyčlenit některé části zdrojového kódu programu do zvláštních souborů, které lze opakovaně používat. Standardní knihovna jazyka C a standardní knihovna jazyka C++ tradičně deklarují své funkce v hlavičkových souborech.

Struktura programu:

Vlastní hlavičkový soubor

Vlastní knihovna musí být ve stejném adresáři jako program.
Využívá se zde podmíněný překlad! Aby se nevkládal vícekrát.

funkce.h

void funkce(void);

funkce.c

void funkce(void) 
 {
  /* ... */
 }

main.c

#include "funkce.h"
int main(void) 
{
  funkce();
  return 0;
}

Všimněte si, že souboru main.c v našem příkladu neodpovídá žádný main.h, neboť v main.c neposkytujeme žádné funkce ani proměnné k použití z jiných souborů.

Podmíněný překlad

Direktivy preprocesoru umožňují předepsat, že v závislosti na určitých podmínkách chceme či nechceme překládat určité úseky zdrojového textu.
V následujícím syntaktickém popisu označuje úsek-programu několik řádků zdrojového textu; úsek programu může být i prázdný, nemusí obsahovat žádný zdrojový text. Může také obsahovat další direktivy preprocesoru, i direktivy pro podmíněný překlad. Každá direktiva musí být stejně jako ostatní direktivy preprocesoru na samostatném řádku.

Syntaxe:
direktivy_pro_podmíněný_překlad:

#if konstantní_výraz nový_řádek 
#ifdef identifikátor nový_řádek 
#ifndef identifikátor nový_řádek 
#elif konstantní_výraz nový_řádek 
#else nový_řádek 
#endif nový_řádek
#ifdef makro1 printf("Definováno makro 1");
#elif makro2 printf("Definováno makro 2");
#else printf("Makro 2 není definováno");
#endif

Podmíněně překládaný úsek programu začíná direktivou #if (nebo #ifdef nebo #ifndef, které slouží jako zkratky pro #if s určitým podmíněným výrazem). Pak může následovat několik úseků začínajících direktivou #elif. Po nich může přijít jeden úsek začínající direktivou #else. Úsek programu s podmíněnou kompilací musí končit direktivou #endif.

Konstantní výrazy mohou obsahovat celočíselné literály, identifikátory definované v direktivě #define a případně operátor defined. V C++ mohou obsahovat i konstanty deklarované pomocí modifikátoru const a inicializované konstantním výrazem.

Význam: V následujícím popisu označuje úsek programu několik řádků zdrojového textu: úsek_programu může být i prázdný, nemusí obsahovat žádný zdrojový text. Může také obsahovat další direktivy preprocesoru, i direktivy pro podmíněný překlad. Každá direktiva musí být stejně jako ostatní direktivy preprocesoru na samostatném řádku.

#if konstantní_výraz_l
  úsek_programu_l 
#elif konstantní_výraz_2 
  úsek_programu_2 
#else usek_programu_3
#endif

Preprocesor vyhodnotí konstantní_výraz_1. Je-li jeho hodnota true (nenulová), přeloží úsek_programu_1. Úseky programu za direktivami #elif a #else ze zdrojového textu vypustí a přejde na zdrojový text za direktivu #endif. Je-li hodnota konstantního_výrazu_1 rovna false, resp. 0, odstraní preprocesor úsek_programu_1 a vyhodnotí konstantní_výraz_2 za #elif. Je-li jeho hodnota nenulová, přeloží úsek_programu_2, odstraní úsek_programu_3 pak přejde za direktivu #endif. Je-li i hodnota konstantního_výrazu_2 rovna false, odstraní se ze zdrojového textu také úsek_programu_2 přeloží úsek_programu_3.

Obvyklá stavba při tvorbě tříd

Když tvořím třídu, deklaraci píšu do souboru s příponou h, do cpp píšu definici (metody).