Funkce a prototypy v C++
Funkce v C++
Bez funkcí se v programování neobejdete. Jsou to vlastně algoritmy, pomocí
kterých pracujete s daty. Určitě jste v matematice brali funkce, tak víte
že musí mít určitý předpis, pomocí kterého se dosáhne požadovaného
výsledku. Do dané funkce se pak dosadí data (jako parametry), s kterými je
poté uvnitř nějakým způsobem manipulováno. Tak to by mohla být stručná
definice pojmu funkce v jazyce C++, ale teď už konkrétněji.
Tak dejme tomu, že chcete vytvořit funkci, která vám spočítá druhou mocninu nějakého čísla. Tato funkce by mohla vypadat třeba takto:
//lekce4.cpp #include <iostream> using namespace std; int Umocni(int x) { return x*x; } int main() { cout << "Zadejte cislo: "; int x; cin >> x; cout << "Druha mocnina cisla " << x <<" je " << Umocni(x) << endl; return 0; }
Tak a funkce je na světě:) Jak jste si jistě všimli, nese název Umocni(), který dokonale vystihuje její účel. Podívejte se ještě jednou na definici funkce:
int Umocni(int x) { return x*x; }
První řádka se nazývá hlavička funkce. Klíčové slovo int před názvem funkce symbolizuje typ návratové hodnoty funkce, tedy typ dat, který je vracen ve funkcí pomocí příkazu return. Zde se jedná konkrétně o celé číslo. Za názvem funkce následují kulaté závorky se seznamem parametrů oddělených čárkou. Tato funkce má pouze jeden parametr typu int. Hlavička funkce je následována tělem funkce, které je uzavřeno do složených závorek. Do těla se zapisují veškeré příkazy, které má funkce vykonat. V tomto případě je zde příkaz xx*, jehož výsledkem je celé číslo, které je místo tohoto výrazu xx* jakoby vnitřně nahrazeno a vráceno příkazem return.
Určitě vám to teď připomíná funkci main(). Je to úplně to samé...
Vytváření funkčních prototypů
Funkční prototypy jsou další věcičkou, která je pro vlastní funkce hodně důležitá. No vlastně ani tak ne pro funkce, jako spíše pro kompilátor. Prorotyp mu totiž říká všechny potřebné informace o funkci, jako je její jméno, návratovou hodnotu a typy parametrů. Jednoduše ho můžete vytvořit tak, že zkopírujete hlavičku funkce a přidáte středník. V předchozím příkladě byl tento prototyp zároveň definicí. Podívejme se tedy, jak můžeme naší funkci upravit, aby byl prototyp vyžadován:
//lekce4.cpp #include <iostream> using namespace std; int Umocni(int x); //Prototyp funkce int main() { cout << "Zadejte cislo: "; int x; cin >> x; cout << "Druha mocnina cisla " << x <<" je " << Umocni(x) << endl; return 0; } int Umocni(int x) { return x*x; }
Pokud by zde prototyp nebyl, kompilátor by nahlásil chybu, že nebyl deklarován identifikátor Umocni. Onou deklarací se rozumí samotný prototyp funkce. Ono je to i celkem logické. Vždyť používáte funkci, o které kompilátor normálně nic neví, neví jaké má očekávat parametry, jejich počet, ani zda popř. jakou vrací hodnotu. Potřebuje tedy znát prototyp této funkce. Tento se umisťuje většinou před definici funkce main(), nebo, ještě častěji, do hlavičkových souborů (ty jsou pak vkládány pomocí directivy #include, jak už víte).
Ukažme si ale ještě jeden případ - ten se používá nejčastěji. Mějme tři soubory - hlavní, s funkcí main(), hlavičkový - s deklarací (neboli prototypem) funkce Umocni, a soubor s její definicí.
Hlavičkový soubor funkce Umocni():
//umocni.h int Umocni(int x);
Soubor s definicí funkce Umocni():
//umocni.cpp int Umocni(int x) { return x*x; }
No a konečně hlavní zdrojový soubor, kde dáme vše dohromady:
//main.cpp #include <iostream> #include "umocni.h" using namespace std; int main() { cout << "Zadejte cislo: "; int x; cin >> x; cout << "Druha mocnina cisla " << x <<" je " << Umocni(x) << endl; return 0; }
Určitě jste si všimli že přibyla jedna directiva #include, která vloží hlavičkový soubor umocni.h - zpřístupní tím deklaraci funkce Umocni(). Pozorný čtenář se jistě pozastavil nad tím, proč je zde soubor v uvozovkách a ne ve zkosených závorkách. Asi bych to měl vysvětlit, jedná se o docela důležitou věc.
Takže popořadě. Pokud používáte nějaké vývojové prostředí, jsou v něm definovány určité absolutní cesty k některým důležitým souborům - ať už hlavičkovým, tak třeba zdrojovým. Ale k čemu nám tahle informace vlastně je? No je to o tom, že pokud použijeme verzi se zkosenými závorkami, tak první věc, kterou preprocesor při zpracování této direktivy udělá je, že prohledá právě tyto cesty. Pokud v žádné z těchto definovaných cest daný soubor nenalezne, nahlásí chybu. U druhé varianty, té s uvozovkami, je to jinak. Zde přímo určujete cestu, ať už absolutně, nebo relativně k umístění souboru, ve kterém je tato direktiva umístěna. Pokud preprocesor soubor nenajde, začne prohledávat cesty definované vývojovým prostředím, viz. výše. Možná by se zde hodila menší poznámka - pokud zadáváte cestu, používejte pro znak lomítka (\\) jeho escape sekvenci (\\\) - tedy dvě lomítka za sebou. Je to proto že lomítko je speciální znak, který uvozuje escape sekvence. Vysvětlení si necháme na jindy, zatím postačí, když místo jednoho lomítka použíjete dvě.:)