Home >> C++ návod >> Funkce 2.část

Funkce 2.část

Jestliže již rozumíte všemu, co jsme si o funkcích řekli v první části, tak nic nebrání tomu pokračovat částí druhou. Pokud však stále nečemu nerozumíte, tak si raději zopakujte ještě jednou první část a pak se sem znovu vraťte.

Proměnná jako parametr funkce

V předchozí části této lekce jsme si vysvětlili, že funkce mohou mít libovolný počet parametrů. Dále víme, že při volání funkce můžeme do těchto paramtrů dosadit jednak konkrétní hodnotu, ale i proměnnou. Pojďme se nyní zabývat tím, co se dějě v případě, že dosadíme proměnnou.

Pro lepší představu použijeme tento jednoduchý příklad:

#include <iostream>
using namespace std;

int cislo = 5;

void vynasob_deseti(int x)
{
x = x * 10;
}

int main ()
{
vynasob_deseti(cislo);
cout << "Hodnota promenne cislo je: " << cislo << endl;
return 0;
}

Výpis programu na obrazovku:

Hodnota promenne cislo je: 5

Teď si možná říkáte: "Chyba! Vypsat se mělo číslo 50", ale věřte tomu, že výpis je naprosto správný. Pokud nevěříte, tak si program klidně odzkoušejte. Pojďme si nyní vysvětlit proč tomu tak je.

V příkladě máme proměnnou cislo = 5 a funkci vynasob_deseti, která výnásobí deseti číslo, které převezme v paramtetru. Hlavní funkce programu je taky jednoduchá, jelikož pouze zavoláme funkci vynasob_deseti, kde jako parametr uvedeme proměnnoucislo a poté hodnotu této proměnné vypíšeme.

Nás však zajimá proč se vypsalo číslo 5 místo 50. Vysvětlení spočívá v parametru funkce. Pokud voláme nějakou funkci a dosadíme do parametru proměnnou, funkce udělá to, že zkopíruje hodnotu proměnné a dále pracuje pouze s touto hodnotou, nikoliv s proměnnou.

V našem příkladě to znamená že :

Při volaní funkce vynasob_deseti(cislo), proměnnácislo pouze předá svoji hodnotu (5) funkci. Ta si ji zkopíruje a dále pracuje pouze z touto hodnotou. Hodnota proměnné cislo tedy zůstavánezměněná.

Co když ale chceme, aby funkce pracovala přímo s proměnnou? V takovém případě musíme trochu upravit parametr funkce. Nemusíte se však vůbec děsit, jelikož tato úprava spočívá pouze v jednom speciálním znaku navíc - & (ampersandu). Tento znak v paramteru přímo následuje datový typ pomocné proměnné a říká překladači, aby pracoval zproměnnou, nikoliv pouze s její hodnotou.

Ukažme si úpravu parametru na předchozím příkladě:

#include <iostream>
using namespace std;

int cislo = 5;

void vynasob_deseti(int& x)
{
x = x * 10;
}

int main ()
{
vynasob_deseti(cislo);
cout << "Hodnota promenne cislo je: " << cislo << endl;
return 0;
}

Výpis programu bude nyní:

Hodnota promenne cislo je: 50

Funkce v tomto případě již pracovala přímo s proměnnou a změnila její hodnotu na50

Defaultní hodnota parametru

Při deklaraci funkce je možné pro parametry nastavit tzv. defaultní hodnotu. Tato hodnota není přidělena parametru natvrdo, značí pouze jakousi výchozí hodnotu, se kterou se bude pracovat v případě, že při volání funkce necháme parametr prázdný. Viz příklad:

#include <iostream>
using namespace std;

void vynasob(int x, int y = 2)
{
int vysledek;
vysledek = x * y;
cout << x << " * " << y << " = " << vysledek << endl;
}

int main ()
{
vynasob(10,5);
vynasob(10);

return 0;
}

V příkladě jsme si vytvořili funkci, která vzájemně vynásobí 2 čísla. Funkce má 2 prametry, přičemž druhému praramteru jsme nastavili defaultní hodnotu 2. V hlavní funkci programu tuto funkci následně dvakrát voláme.

V prvním případě jsme vyplnili oba parametry. První číslem 10 a druhý číslem 5, což znamená, že defaultní hodnota se nepoužije a tyto dvě čísla se vynásobí.

V druhém případě jsme vyplnili pouze jeden parametr a druhý zůstal prázdný. Ve funkci je však druhý parametr defaultně nastaven na 2. To znamená, že násobit se budou čísla 10 a 2.

Výpis programu:

10 * 5 = 50
10 * 2 = 20

Funkce se stejným jménem

V C++ je možné ruzné funkce pojmenovat stejně. Takové funkce však musí mít buď rozdílný datový typ nebo rozdílný počet parametrů. Příklad:

#include <iostream>
using namespace std;

int vynasob(int x, int y){
return x * y;
}

int vynasob(int x, int y, int z){
return x * y * z;
}

int main ()
{
cout << vynasob(10,10) << endl;
cout << vynasob(10,10,10) << endl;
return 0;
}

V příkladě jsme deklarovali dvě funkce se stejným jménem. Tento zápis je možný protože splňuje jednu ze dvou podmínek, které jsme si uvedli na začátku - rozdílný počet paramterů. Zatímco jedna funkce akceptuje 2 parametry, druhá akceptuje 3 parametry.

Výstup programu:

100
1000

Funkce volající druhou funkci

Nyní si ukážeme, že funkce může volat funkci jinou. V takovém případě si musíme uvědomit jednu důležitou věc a to pořadí funkcí ve zdrojovém kódu. Vezměme si tento příklad:

#include <iostream>
using namespace std;

void druha(){
cout << "Probehla druha funkce" << endl;
}

void prvni(){
cout << "Probehla prvni funkce" << endl;
druha();
}

int main(void)
{
prvni();
return 0;
}

Tento příklad je opravdu velmi jednoduchý, ale k našemu účelu nám plně postačí. Deklarovali jsme 2 funkce se jmény prvni a druha. Obě funkce pouze vypíšou krátkou zprávu, která nám dokáže, že funkce proběhla. Funkce prvni však obsahuje ještě příkaz na volání funkce druha.

Myslím si, že již není nutné dlouze popisovat, co se bude dít, ale aspoň tedy ve zkratce. Nejprve proběhne první funkce. Ta vypíše svoji zprávu a zavolá funkci druhou. Druhá funkce rovněž vypíše svoji zprávu. Výstup programu tedy vypadá následovně:

Probehla prvni funkce
Probehla druha funkce

Určitě jste si všimli pořadí funkcí ve zdrojovém kódu. Toto pořadí není vůbec náhodné a opačně by program nešel přeložit. Funkce druha musí být totiž uvedena ve zdrojovém kódu dříve než funkce prvni. Pro lepší představu proč tomu tak je, funkce z předchozího příkladu prohodíme:

#include <iostream>
using namespace std;

void prvni(){
cout << "Probehla prvni funkce" << endl;
druha();
}

void druha(){
cout << "Probehla druha funkce" << endl;
}

int main(void)
{
prvni();
return 0;
}

Pokud se pokusíme tento program přeložit, dostaneme hlášku:

error: 'druha' was not declared in this scope

Pokud si tuto hlášku přeložíme do češtiny, dostaneme něco jako:

chyba: funkce druha není v této oblasti deklarována

Pojďme si vysvětlit v čem je chyba. Již víme, že program je zpracováván shora řádek po řádku. Problém tedy spočívá v tom, že ve chvíli, kdy zavoláme první funkci, tak se dostaneme ve zdrojovém kódu postupně od prvního řádku na řádek, kde je tato funkce zapsána a odtud pokračujeme již zmiňovaným směrem dolů.

Následuje řádek z příkazem pro výpis. Tady je vše ještě v pořádku. Chyba nastane na řádku následujícím, kde voláme funkci druhou. Jelikož druhá funkce nebyla nikde předtím deklarována, překladač se tvaří jakoby druhá funkce neexistovala a dostaneneme výše uvedenou chybovou hlášku.

Tento problém odstraníme tím, že zaměníme pořadí funkcí ve zdrojovém kódu. V takovém případě se program již v pořádku přeloží, jelikož ve chvíli kdy první funkce volá druhou, byla tato funkce již dříve deklarována.

Rekurzivní funkce

Poslední věcí, kterou si v této lekci představíme je tzv. rekurzivní funkce. Tato funkce je zvláštní a zároveň užitečná v tom, že vlastně volá sama sebe. Pro lepší představu se podívejme na tento příklad:

#include <iostream>
using namespace std;

void odpocet(int x){
  if (x > 0){
  cout << x << ", ";
  odpocet(x-1);
  }
  else cout << "Ted!" << endl;
}

int main(void)
{
odpocet(10);
return 0;
}

V příkladě jsme deklarovali funkci odpocet, která odpočítavá a průběžně vypisuje hodnoty až do chvíle, kdy se hodnota proměnné x dostane na nulu. V ten moment se vypíše slovo Ted!. Funkce ve svém těle obsahuje příkaz na volání sama sebe, jedná se tedy o funkci rekurzivní. Tímto speciálním voláním jsme dosáhli toho, že se funkce chová jako cyklus s podmínkou (x > 0).

C++ Návod
Úvod do C++
Volba programu
Struktura programu
Proměnné
Konstanty
Operátory
Vstup a výstup
Řídící struktury
Funkce - 1.část
Funkce - 2.část
Pole
Práce s textovými řetězci
Ukazatele - 1.část
Ukazatele - 2.část
Dynamické proměnné
Datové struktury
©2008 - 2011 Klikzone.cz
Ráj aut - inzerce nových i ojetých aut