Funkce
Funkce
Co je to funkce?
Funkce je pojmenovaná množina příkazů, kterou lze volat z jiných částí programu.
Jaké jsou výhody funkcí?
·Šetří paměť (množina příkazů je zapsaná pouze jednou)
·Zpřehledňují program
Funkce je samostatná jednotka, která může být samostatně vytvářena a upravována
Kterou funkci obsahuje každý C/C++ program a čím je tato funkce výjimečná?
Každý C/C++ program obsahuje právě 1 funkci main.
Touto funkcí začíná vykonávání programu.
Jak dělíme funkce?
· standardní
· uživatelské
· podpůrné a nadstavbové
Co víte o knihovních funkcích – uveďte příklad!
· jsou definovány normou jazyka - knihovní funkce
· deklarace je popsána v hlavičkových souborech
· nemáme k dispozici jejich zdrojový kód
Příklady: scanf, printf, getchar, putchar, sin, cos, tan,…
Jak vytváříme vlastní funkce?
Před mainem uvedeme prototyp, za mainem definici funkce
Před mainem uvedeme celou definici funkce.
7. Co to je prototyp funkce a k čemu slouží?
Prototyp funkce:
Hlavička, ukončená středníkem.
Navratovy-typ jmeno(seznam parametru);
Překladač potřebuje znát tyto informace, aby mohl správně zpracovat volání funkce.
Uveďte obecnou definici funkce!
Obecný formát funkce:
Navratovy-typ jmeno(seznam parametru) // hlavička
{
Prikazy; // Tělo funkce
}
Co to je návratový typ funkce?
Navratovy-typ je typ dat vracených funkcí pomocí příkazu return.
Určuje hodnotu vraceného datového typu (lze použít void).
Návratová hodnota je výsledkem výrazu za return.
return výraz_vhodného_typu;
Příklad definice funkce s návratovou hodnotou:
int isqr(int i){return i * i;}
Jaký příkaz musí obsahovat funkce s návratovou hodnotou uvnitř své příkazové části a jaký má význam?
Příkaz return
Ukončí činnost funkce a předá řízení programu bezprostředně za místem, z něhož byla funkce volána.
Vysvětlete pojmy deklarace a definice funkce!
Definice funkce je kompletní napsání funkce (její hlavičky a těla).
Deklarace funkce je uvedení jejího prototypu (překladači to stačí).
Vysvětlete rozdíl mezi lokálními a globálními deklaracemi!
Globální deklarace jsou uvedeny nad všemi funkcemi
Lokální deklarace jsou uvedeny v některé funkci
Co znamená zastínění identifikátoru – uveďte příklad!
Použijeme-li ve funkci identifikátor stejného jména, jako má globální proměnná
Jak můžeme přistupovat k zastíněnému globálnímu odentifikátoru?
Pomocí operátoru ::
#include <stdio.h>
int a=1;
main(){
int a=0;
printf("Lokalni a: %d\n",a);
printf("Globalni a: %d\n",::a);
}
Jaké znáte argumenty (parametry) funkcí a způsob jejich předávání?
Jsou 3 možnosti předávání parametrů funkci (volání funkce):
· hodnotou
· odkazem ( v C++)
· adresou
void zmena(int x, int y){
int temp = x;
x = y;
y = temp;
}
// Použití – nedojde ke změně obsahu a,b
int a = 10;
int b = 5;
zmena(a, b);
Aby došlo ke změně, nutno předat parametry odkazem:
void zmena(int &x, int &y){
int temp = x;
x = y;
y = temp;
}
// Použití – nyní už dojde ke změně obsahu a,b
main(){
int a = 10;
int b = 5;
zmena(a,b); // volání je stejné jako hodnotou
}
Chcete-li, aby funkce změnila obsah argumentů (skutečných parametrů), použijte volání odkazem – bylo zavedeno až v C++.
Čím je tvořeno funkční rozhraní?
Funkční rozhraní je způsob komunikace mezi funkcí a volající jednotkou:
· Přes globální proměnné – nedoporučuje se, mohou vzniknout tzv. vedlejší efekty
· Přes parametry
· Pomocí návratové hodnoty
Co je to volání funkce?
Uvedení jména funkce včetně jejich skutečných parametrů (argumentů) v kulatých závorkách.
Jak musíme volat funkci, chceme-li využít její návratovou hodnotu?
Na pravé straně příkazu přiřazení S=obsah(10,20);
V rámci příkazu printf(“%f“, obsah(10,20));
Co jsou formální a skutečné parametry (argumenty) – uveďte příklad!
Formální parametry jsou parametry, uvedené v kulatých závorkách v definici funkce
Skutečné parametry jsou parametry, uvedené v kulatých závorkách při volání funkce.
Kolik argumentů lze funkci předat podle normy ANSI C?
Norma ANSI C předepisuje možnost předat funkci až 31 argumentů .
Uveďte příklad funkce bez parametrů a návratové hodnoty!
PříkladPozdrav1(){
printf(”Dobry den\n”);
}
Pozdrav2(){printf(”Nazdar\n ”);
}
main(){
Pozdrav1();
Pozdrav2();
}
Jiná možnost psaní programu: před mainem se uvedou prototypy funkcí, definice funkcí se uvedou za mainem.
Pozdrav1();
Pozdrav2();
main(){
Pozdrav1();
Pozdrav2();
}
Pozdrav1(){
printf(”Dobry den\n”);
}
Pozdrav2(){
printf(”Nazdar\n ”);
}
sum(){
int a,b;
scanf("%f %f”,&a,&b);
printf("%f”, a+b);
}
main(){
float c;
sum();
}
Uveďte příklad funkce bez parametrů s návratovou hodnotou!
Použití funkcí pro vracení hodnot
Vytvořili jsme program pro výpočet goniometrických funkcí, kde jsme použili funkci:
y=sin(x);
Při psaní vlastních funkcí můžete vracet hodnotu pomocí příkazu return.
float sum(){
float a,b;
scanf("%f %f",&a,&b);
return a+b;
}
main(){
float c;
c=sum();
printf(“%f”,c);
}
Když se ve funkci dojde na příkaz return, funkce ihned končí.
Return lze použít i samostatně bez vracené hodnoty:
return;
Ve funkci může být více příkazů return.
Uveďte příklad funkce s parametry!
Použití argumentů funkce
Argument funkce je hodnota, která se předává funkci při jejím volání.
Norma ANSI C určuje, že funkci musí být možné předat 31 argumentů.
Argumenty se předávají do speciálních proměnných – tzv. formálních parametrů funkce.
Parametry se deklarují v závorkách za jménem funkce.
y=sin(x);
Argument je zde hodnota promìnné x.
sum(float x, float y);
main(){
sum(10,20);
sum(1,1);
sum(12.5,13.6);
}
sum(float x, float y){
printf("%f",x+y);
}
Funkce, které přebírají parametry se nazývají parametrizované funkce.
Musíte zadat typ a jméno každého parametru a má-li funkce více parametrů, musíte je oddělit čárkami.
Počet a typ argumentů musí být stejný jako počet a typ parametrů.
Vysvětlete předávání parametrů hodnotou – uveďte prototyp a volání!
Hodnoty skutečných argumentů jsou předány do zásobníku.
Formální argumenty se odkazují na odpovídající místa v zásobníku (kopie skutečných argumentů).
Změna hodnoty formálního parametru se nepromítne do změny hodnoty argumentů
Problém vzniká v okamžiku, kdy potřebujeme, aby funkce vrátila více než jednu hodnotu.
Řešení pomocí globální proměnné se nepovažuje za vhodné (vedlejší účinky)
Prototyp:
int secti (int a, int b;
Volání:
int x=10,y=20,z;
z=secti(x,y);
Vysvětlete předávání parametrů odkazem– uveďte prototyp a volání!
Odkaz je ukazatel, který vystupuje jako další jméno proměnné.
Může být funkci předán
Může být funkcí vrácen
Příklad předávání parametrů odkazemFunkce obsah_a_obvod(float a,float b,float &s,float &o) počítá obsah a obvod obdélníka, jehož strany jsou do funkce přenášeny jako parametry.
Vypočítané hodnoty funkce vrací do volající jednotky přes parametry volané odkazem s a o.
Volání odkazem je vyjádřeno znakem & před parametrem.
#include <stdio.h>
obsah_a_obvod(float a,float b,float &s,float &o){
s=a*b;
o=2*(a+b);
}
main(){
float a,b,s,o;
scanf("%f %f",&a,&b);
obsah_a_obvod( a, b, s, o);
printf("Plocha: %f\n",s);
printf("Obvod: %f\n",o);
}
Funkce vypocty realizuje všechny možné aritmetické operace s s prvními dvěma parametry, které jsou předávány hodnotou.
Výsledky výpočtů jsou předávány pomocí dalších čtyř parametrů odkazem.
#include <stdio.h>
vypocty(float a,float b,float &s,float &r,float &k,float &p){
s=a+b;
r=a-b;
k=a*b;
p=a/b;
}
main(){
float a,b,s,r,k,p;
scanf("%f %f",&a,&b);
vypocty( a, b, s, r,k,p);
printf("Soucet: %f\n",s);
printf("Rozdil: %f\n",r);
printf("Soucin: %f\n",k);
printf("Podil: %f\n",p);
}
Příklad vracení odkazu#include <stdio.h>
int &f();
int x;
main() {
f()=100;// prirazeni 100 odkazu, vracenemu f()
printf("%d\n",x);
}
int &f(){
return x;//vraci odkaz na x
}
Co jsou rekurzivní funkce?
Rekurzivní funkce, je funkce, která volá sama sebe, a to buď:
Přímo
Nepřímo – přes jiné funkce
#include <stdio.h>
int fak(int n){
if(n==0)return 1;
else return n*fak(n-1);
}
main(){
int n;
printf("Zadej n: ");
scanf("%d",&n);
printf("%d",fak(n));
}
Jak zajistíme aby rekurzivní funkce nebyla nekonečná?
Funkce musí obsahovat podmínku, při jejímž splnění dojde k návratu z funkce, při kterém už nedochází k rekurzivnímu volání.
if(n==0)return 1;
else return n*fak(n-1);
Co jsou in-line funkce?
Rozdělení programu na funkce je jedním z důležitých prvků strukturovaného programování.
Někdy nám však může vadit, že volání funkce chvíli trvá.
Nemáme teď na mysli samotný kód, který je ve funkci, ale kód, který se musí vykonat pro to, aby se funkce vůbec vyvolala a úspěšně se vrátila po jejím skončení.
Pokud máme funkci, která obsahuje velmi primitivní kód, je dost možné, že samotné volání funkce bude trvat déle, než tělo funkce.
V jazyce C se tento problém řešil pomocí maker, v C++ pomocí inline funkcí.
Inline funkce je na první pohled úplně normální funkce.
Rozdíl je až ve volání funkce, protože překladač místo aby inline funkci volal, vloží její kód na místo volání. Vykonání funkce je pak samozřejmě mnohem rychlejší.
Funkci prohlásíme jako inline, když před definici funkce uvedeme klíčové slovo inline, třeba takto:
// Nějaká inline funkce
inline int Fce(int x, int y)
{
return x*y;
}
Funkce nevhodné jako inline :
příliš komplikované funkce
rekurzivní funkce a
ukazatele na funkce
Rekurzivní funkce (funkce, která volá sebe sama) celkem logicky přinášejí potíže, když se je pokoušíme vytvářet jako inline, neboť víme, že místo volání funkce, se vkládá přímo tělo funkce.
V případě rekurze by pak došlo k zacyklení překladače
(a je jedno, zda je rekurze konečná nebo ne).
Co jsou implicitní parametry funkcí
Pokud programujeme v C++, můžeme si situaci výrazně zjednodušit pomocí implicitních parametrů funkcí. Jedná se o to, že některým parametrům funkce přiřadíme výchozí hodnotu a poté se při volání funkce nemusí uvádět skutečný parametr. Pokud není uveden, chápe se volání funkce, jako bychom předali na místě skutečného parametru hodnotu, která je uvedena jako implicitní. Pokud skutečný parametr uvedeme, pak se použije tento a implicitní hodnota se ignoruje.
Implicitní parametr definujeme tak, že buď do deklarace, nebo do definice funkce uvedeme za daný parametr rovnítko a za něj implicitní hodnotu. Implicitní hodnotou může být prakticky cokoliv, tedy nejen konstanta, ale i proměnná, volání funkce nebo výraz. Jak si ukážeme později, je implicitní hodnotou většinou konstanta. Musíme se taktéž mít na pozoru před tím, že definice implicitních parametrů musí být buď v deklaraci funkce, nebo v definici, ale nikdy v obou, protože to je chápáno překladačem jako chyba. Z konvence je však doporučeno, aby implicitní parametry byly definovány vždy v deklaraci funkce.
// Funkce vrátí mocninu nBase na nExp. Druhý parametr
// je implicitní a je roven dvěma.
#include <stdio.h>
int Power(int nBase, int nExp = 2) //definice implicitního parametru
{
int nValue = 1;
// Postupne násobíme základ...
while (nExp > 0)
{
nValue *= nBase;
nExp--;
}
return nValue;
}
void main()
{
int nValue;
// pet na druhou - pouzije se implicitní parametr
nValue = Power(5);
printf("%d\n",nValue);
// pet na druhou - bez implicitního parametru
nValue = Power(5, 2);
printf("%d\n",nValue);
// pet na tretí
nValue = Power(5, 3);
printf("%d\n",nValue);
}
Jak je vidět, tak příklad není úplně nesmyslný, protože většinou potřebujeme mocninu dvou, což nám zajišťuje implicitní parametr. Vystačíme si tedy s jednou funkcí, místo se dvěma. Bohužel nic není dokonalé, tedy ani jazyk C++, implicitní parametry nevyjímaje. Při definici implicitních parametrů totiž nemáme úplnou svobodu, musíme se totiž držet následujících pravidel:
· Pokud definujeme nějaký parametr jako implicitní, musí být i všechny parametry vpravo od něj taktéž implicitní.
· Pokud uvedeme při volání funkce hodnotu nějakého implicitního parametru, musíme uvést i hodnoty všech implicitních parametrů vlevo od něj.
Co jsou přetížené funkce
Přetížená funkce je taková funkce, která má pod jedním názvem skryto více definic.
Příklad (pouze deklarace):
// Absolutní hodnota dlouhého celého čísla
long lAbs(long x);
// Asolutní hodnota reálného čísla
double fAbs(double x);
// Absolutní hodnota matice (Matice bude typ struktura)
Matice mAbs(Matice x);
// Absolutní hodnota komplexního čísla (Komplex je struktura)
double cAbs(Komplex x);
Takto bychom museli postupovat v jazyku C, ale v C++ máme díky možnosti přetěžování funkcí jinou možnost. Nevýhodou předchozího řešení je, že si uživatel musí pamatovat velké množství funkcí. Sice jsme se pokusili názvy zvolit dostatečně jasně, ale jak uvidíme později, lze to i jednodušeji, třeba takto (opět jenom deklarace):
// Absolutní hodnota dlouhého celého číslo
long Abs(long x);
// Asolutní hodnota reálného čísla
double Abs(double x);
// Absolutní hodnota matice (Matice bude typ struktura)
Matice Abs(Matice x);
// Absolutní hodnota komplexního čísla (Komplex je struktura)
double Abs(Komplex x);
Máme zde pouze jeden název funkce: Abs, ale jsou zde čtyři různé definice funkce (které jsme si zde neuvedli - definice funkce = tělo funkce). Je asi jasné, že definice funkcí se budou lišit, protože algoritmus výpočtu absolutní hodnoty komplexního čísla je naprosto odlišný od výpočtu absolutní hodnoty celého čísla. Překladač sám pozná při překladu volání funkce, kterou z přetížených verzí máme na mysli. Rozlišovacím znamením jsou počet nebo typy parametrů. Z toho plyne i omezení při přetěžování funkcí (nebo metod), kdy je nutné, aby se jednotlivé přetížené funkce lišily počtem parametrů nebo jejich typem.
printf(”Nazdar\n ”);
}
main(){
Pozdrav1();
Pozdrav2();
}
Jiná možnost psaní programu: před mainem se uvedou prototypy funkcí, definice funkcí se uvedou za mainem.
Pozdrav1();
Pozdrav2();
main(){
Pozdrav1();
Pozdrav2();
}
Pozdrav1(){
printf(”Dobry den\n”);
}
Pozdrav2(){
printf(”Nazdar\n ”);
}
sum(){
int a,b;
scanf("%f %f”,&a,&b);
printf("%f”, a+b);
}
main(){
float c;
sum();
}
Uveďte příklad funkce bez parametrů s návratovou hodnotou!
Použití funkcí pro vracení hodnot
Vytvořili jsme program pro výpočet goniometrických funkcí, kde jsme použili funkci:
y=sin(x);
Při psaní vlastních funkcí můžete vracet hodnotu pomocí příkazu return.
float sum(){
float a,b;
scanf("%f %f",&a,&b);
return a+b;
}
main(){
float c;
c=sum();
printf(“%f”,c);
}
Když se ve funkci dojde na příkaz return, funkce ihned končí.
Return lze použít i samostatně bez vracené hodnoty:
return;
Ve funkci může být více příkazů return.
Uveďte příklad funkce s parametry!
Použití argumentů funkce
Argument funkce je hodnota, která se předává funkci při jejím volání.
Norma ANSI C určuje, že funkci musí být možné předat 31 argumentů.
Argumenty se předávají do speciálních proměnných – tzv. formálních parametrů funkce.
Parametry se deklarují v závorkách za jménem funkce.
y=sin(x);
Argument je zde hodnota promìnné x.
sum(float x, float y);
main(){
sum(10,20);
sum(1,1);
sum(12.5,13.6);
}
sum(float x, float y){
printf("%f",x+y);
}
Funkce, které přebírají parametry se nazývají parametrizované funkce.
Musíte zadat typ a jméno každého parametru a má-li funkce více parametrů, musíte je oddělit čárkami.
Počet a typ argumentů musí být stejný jako počet a typ parametrů.
Vysvětlete předávání parametrů hodnotou – uveďte prototyp a volání!
Hodnoty skutečných argumentů jsou předány do zásobníku.
Formální argumenty se odkazují na odpovídající místa v zásobníku (kopie skutečných argumentů).
Změna hodnoty formálního parametru se nepromítne do změny hodnoty argumentů
Problém vzniká v okamžiku, kdy potřebujeme, aby funkce vrátila více než jednu hodnotu.
Řešení pomocí globální proměnné se nepovažuje za vhodné (vedlejší účinky)
Prototyp:
int secti (int a, int b;
Volání:
int x=10,y=20,z;
z=secti(x,y);
Vysvětlete předávání parametrů odkazem– uveďte prototyp a volání!
Odkaz je ukazatel, který vystupuje jako další jméno proměnné.
Může být funkci předán
Může být funkcí vrácen
Příklad předávání parametrů odkazemFunkce obsah_a_obvod(float a,float b,float &s,float &o) počítá obsah a obvod obdélníka, jehož strany jsou do funkce přenášeny jako parametry.
Vypočítané hodnoty funkce vrací do volající jednotky přes parametry volané odkazem s a o.
Volání odkazem je vyjádřeno znakem & před parametrem.
#include <stdio.h>
obsah_a_obvod(float a,float b,float &s,float &o){
s=a*b;
o=2*(a+b);
}
main(){
float a,b,s,o;
scanf("%f %f",&a,&b);
obsah_a_obvod( a, b, s, o);
printf("Plocha: %f\n",s);
printf("Obvod: %f\n",o);
}
Funkce vypocty realizuje všechny možné aritmetické operace s s prvními dvěma parametry, které jsou předávány hodnotou.
Výsledky výpočtů jsou předávány pomocí dalších čtyř parametrů odkazem.
#include <stdio.h>
vypocty(float a,float b,float &s,float &r,float &k,float &p){
s=a+b;
r=a-b;
k=a*b;
p=a/b;
}
main(){
float a,b,s,r,k,p;
scanf("%f %f",&a,&b);
vypocty( a, b, s, r,k,p);
printf("Soucet: %f\n",s);
printf("Rozdil: %f\n",r);
printf("Soucin: %f\n",k);
printf("Podil: %f\n",p);
}
Příklad vracení odkazu#include <stdio.h>
int &f();
int x;
main() {
f()=100;// prirazeni 100 odkazu, vracenemu f()
printf("%d\n",x);
}
int &f(){
return x;//vraci odkaz na x
}
Co jsou rekurzivní funkce?
Rekurzivní funkce, je funkce, která volá sama sebe, a to buď:
Přímo
Nepřímo – přes jiné funkce
#include <stdio.h>
int fak(int n){
if(n==0)return 1;
else return n*fak(n-1);
}
main(){
int n;
printf("Zadej n: ");
scanf("%d",&n);
printf("%d",fak(n));
}
Jak zajistíme aby rekurzivní funkce nebyla nekonečná?
Funkce musí obsahovat podmínku, při jejímž splnění dojde k návratu z funkce, při kterém už nedochází k rekurzivnímu volání.
if(n==0)return 1;
else return n*fak(n-1);
Co jsou in-line funkce?
Rozdělení programu na funkce je jedním z důležitých prvků strukturovaného programování.
Někdy nám však může vadit, že volání funkce chvíli trvá.
Nemáme teď na mysli samotný kód, který je ve funkci, ale kód, který se musí vykonat pro to, aby se funkce vůbec vyvolala a úspěšně se vrátila po jejím skončení.
Pokud máme funkci, která obsahuje velmi primitivní kód, je dost možné, že samotné volání funkce bude trvat déle, než tělo funkce.
V jazyce C se tento problém řešil pomocí maker, v C++ pomocí inline funkcí.
Inline funkce je na první pohled úplně normální funkce.
Rozdíl je až ve volání funkce, protože překladač místo aby inline funkci volal, vloží její kód na místo volání. Vykonání funkce je pak samozřejmě mnohem rychlejší.
Funkci prohlásíme jako inline, když před definici funkce uvedeme klíčové slovo inline, třeba takto:
// Nějaká inline funkce
inline int Fce(int x, int y)
{
return x*y;
}
Funkce nevhodné jako inline :
příliš komplikované funkce
rekurzivní funkce a
ukazatele na funkce
Rekurzivní funkce (funkce, která volá sebe sama) celkem logicky přinášejí potíže, když se je pokoušíme vytvářet jako inline, neboť víme, že místo volání funkce, se vkládá přímo tělo funkce.
V případě rekurze by pak došlo k zacyklení překladače
(a je jedno, zda je rekurze konečná nebo ne).
Co jsou implicitní parametry funkcí
Pokud programujeme v C++, můžeme si situaci výrazně zjednodušit pomocí implicitních parametrů funkcí. Jedná se o to, že některým parametrům funkce přiřadíme výchozí hodnotu a poté se při volání funkce nemusí uvádět skutečný parametr. Pokud není uveden, chápe se volání funkce, jako bychom předali na místě skutečného parametru hodnotu, která je uvedena jako implicitní. Pokud skutečný parametr uvedeme, pak se použije tento a implicitní hodnota se ignoruje.
Implicitní parametr definujeme tak, že buď do deklarace, nebo do definice funkce uvedeme za daný parametr rovnítko a za něj implicitní hodnotu. Implicitní hodnotou může být prakticky cokoliv, tedy nejen konstanta, ale i proměnná, volání funkce nebo výraz. Jak si ukážeme později, je implicitní hodnotou většinou konstanta. Musíme se taktéž mít na pozoru před tím, že definice implicitních parametrů musí být buď v deklaraci funkce, nebo v definici, ale nikdy v obou, protože to je chápáno překladačem jako chyba. Z konvence je však doporučeno, aby implicitní parametry byly definovány vždy v deklaraci funkce.
// Funkce vrátí mocninu nBase na nExp. Druhý parametr
// je implicitní a je roven dvěma.
#include <stdio.h>
int Power(int nBase, int nExp = 2) //definice implicitního parametru
{
int nValue = 1;
// Postupne násobíme základ...
while (nExp > 0)
{
nValue *= nBase;
nExp--;
}
return nValue;
}
void main()
{
int nValue;
// pet na druhou - pouzije se implicitní parametr
nValue = Power(5);
printf("%d\n",nValue);
// pet na druhou - bez implicitního parametru
nValue = Power(5, 2);
printf("%d\n",nValue);
// pet na tretí
nValue = Power(5, 3);
printf("%d\n",nValue);
}
Jak je vidět, tak příklad není úplně nesmyslný, protože většinou potřebujeme mocninu dvou, což nám zajišťuje implicitní parametr. Vystačíme si tedy s jednou funkcí, místo se dvěma. Bohužel nic není dokonalé, tedy ani jazyk C++, implicitní parametry nevyjímaje. Při definici implicitních parametrů totiž nemáme úplnou svobodu, musíme se totiž držet následujících pravidel:
· Pokud definujeme nějaký parametr jako implicitní, musí být i všechny parametry vpravo od něj taktéž implicitní.
· Pokud uvedeme při volání funkce hodnotu nějakého implicitního parametru, musíme uvést i hodnoty všech implicitních parametrů vlevo od něj.
Co jsou přetížené funkce
Přetížená funkce je taková funkce, která má pod jedním názvem skryto více definic.
Příklad (pouze deklarace):
// Absolutní hodnota dlouhého celého čísla
long lAbs(long x);
// Asolutní hodnota reálného čísla
double fAbs(double x);
// Absolutní hodnota matice (Matice bude typ struktura)
Matice mAbs(Matice x);
// Absolutní hodnota komplexního čísla (Komplex je struktura)
double cAbs(Komplex x);
Takto bychom museli postupovat v jazyku C, ale v C++ máme díky možnosti přetěžování funkcí jinou možnost. Nevýhodou předchozího řešení je, že si uživatel musí pamatovat velké množství funkcí. Sice jsme se pokusili názvy zvolit dostatečně jasně, ale jak uvidíme později, lze to i jednodušeji, třeba takto (opět jenom deklarace):
// Absolutní hodnota dlouhého celého číslo
long Abs(long x);
// Asolutní hodnota reálného čísla
double Abs(double x);
// Absolutní hodnota matice (Matice bude typ struktura)
Matice Abs(Matice x);
// Absolutní hodnota komplexního čísla (Komplex je struktura)
double Abs(Komplex x);
Máme zde pouze jeden název funkce: Abs, ale jsou zde čtyři různé definice funkce (které jsme si zde neuvedli - definice funkce = tělo funkce). Je asi jasné, že definice funkcí se budou lišit, protože algoritmus výpočtu absolutní hodnoty komplexního čísla je naprosto odlišný od výpočtu absolutní hodnoty celého čísla. Překladač sám pozná při překladu volání funkce, kterou z přetížených verzí máme na mysli. Rozlišovacím znamením jsou počet nebo typy parametrů. Z toho plyne i omezení při přetěžování funkcí (nebo metod), kdy je nutné, aby se jednotlivé přetížené funkce lišily počtem parametrů nebo jejich typem.
#include <stdio.h>
int &f();
int x;
main() {
f()=100;// prirazeni 100 odkazu, vracenemu f()
printf("%d\n",x);
}
int &f(){
return x;//vraci odkaz na x
}
Co jsou rekurzivní funkce?
Rekurzivní funkce, je funkce, která volá sama sebe, a to buď:
Přímo
Nepřímo – přes jiné funkce
#include <stdio.h>
int fak(int n){
if(n==0)return 1;
else return n*fak(n-1);
}
main(){
int n;
printf("Zadej n: ");
scanf("%d",&n);
printf("%d",fak(n));
}
Jak zajistíme aby rekurzivní funkce nebyla nekonečná?
Funkce musí obsahovat podmínku, při jejímž splnění dojde k návratu z funkce, při kterém už nedochází k rekurzivnímu volání.
if(n==0)return 1;
else return n*fak(n-1);
Co jsou in-line funkce?
Rozdělení programu na funkce je jedním z důležitých prvků strukturovaného programování.
Někdy nám však může vadit, že volání funkce chvíli trvá.
Nemáme teď na mysli samotný kód, který je ve funkci, ale kód, který se musí vykonat pro to, aby se funkce vůbec vyvolala a úspěšně se vrátila po jejím skončení.
Pokud máme funkci, která obsahuje velmi primitivní kód, je dost možné, že samotné volání funkce bude trvat déle, než tělo funkce.
V jazyce C se tento problém řešil pomocí maker, v C++ pomocí inline funkcí.
Inline funkce je na první pohled úplně normální funkce.
Rozdíl je až ve volání funkce, protože překladač místo aby inline funkci volal, vloží její kód na místo volání. Vykonání funkce je pak samozřejmě mnohem rychlejší.
Funkci prohlásíme jako inline, když před definici funkce uvedeme klíčové slovo inline, třeba takto:
// Nějaká inline funkce
inline int Fce(int x, int y)
{
return x*y;
}
Funkce nevhodné jako inline :
příliš komplikované funkce
rekurzivní funkce a
ukazatele na funkce
Rekurzivní funkce (funkce, která volá sebe sama) celkem logicky přinášejí potíže, když se je pokoušíme vytvářet jako inline, neboť víme, že místo volání funkce, se vkládá přímo tělo funkce.
V případě rekurze by pak došlo k zacyklení překladače
(a je jedno, zda je rekurze konečná nebo ne).
Co jsou implicitní parametry funkcí
Pokud programujeme v C++, můžeme si situaci výrazně zjednodušit pomocí implicitních parametrů funkcí. Jedná se o to, že některým parametrům funkce přiřadíme výchozí hodnotu a poté se při volání funkce nemusí uvádět skutečný parametr. Pokud není uveden, chápe se volání funkce, jako bychom předali na místě skutečného parametru hodnotu, která je uvedena jako implicitní. Pokud skutečný parametr uvedeme, pak se použije tento a implicitní hodnota se ignoruje.
Implicitní parametr definujeme tak, že buď do deklarace, nebo do definice funkce uvedeme za daný parametr rovnítko a za něj implicitní hodnotu. Implicitní hodnotou může být prakticky cokoliv, tedy nejen konstanta, ale i proměnná, volání funkce nebo výraz. Jak si ukážeme později, je implicitní hodnotou většinou konstanta. Musíme se taktéž mít na pozoru před tím, že definice implicitních parametrů musí být buď v deklaraci funkce, nebo v definici, ale nikdy v obou, protože to je chápáno překladačem jako chyba. Z konvence je však doporučeno, aby implicitní parametry byly definovány vždy v deklaraci funkce.
// Funkce vrátí mocninu nBase na nExp. Druhý parametr
// je implicitní a je roven dvěma.
#include <stdio.h>
int Power(int nBase, int nExp = 2) //definice implicitního parametru
{
int nValue = 1;
// Postupne násobíme základ...
while (nExp > 0)
{
nValue *= nBase;
nExp--;
}
return nValue;
}
void main()
{
int nValue;
// pet na druhou - pouzije se implicitní parametr
nValue = Power(5);
printf("%d\n",nValue);
// pet na druhou - bez implicitního parametru
nValue = Power(5, 2);
printf("%d\n",nValue);
// pet na tretí
nValue = Power(5, 3);
printf("%d\n",nValue);
}
Jak je vidět, tak příklad není úplně nesmyslný, protože většinou potřebujeme mocninu dvou, což nám zajišťuje implicitní parametr. Vystačíme si tedy s jednou funkcí, místo se dvěma. Bohužel nic není dokonalé, tedy ani jazyk C++, implicitní parametry nevyjímaje. Při definici implicitních parametrů totiž nemáme úplnou svobodu, musíme se totiž držet následujících pravidel:
· Pokud definujeme nějaký parametr jako implicitní, musí být i všechny parametry vpravo od něj taktéž implicitní.
· Pokud uvedeme při volání funkce hodnotu nějakého implicitního parametru, musíme uvést i hodnoty všech implicitních parametrů vlevo od něj.
Co jsou přetížené funkce
Přetížená funkce je taková funkce, která má pod jedním názvem skryto více definic.
Příklad (pouze deklarace):
// Absolutní hodnota dlouhého celého čísla
long lAbs(long x);
// Asolutní hodnota reálného čísla
double fAbs(double x);
// Absolutní hodnota matice (Matice bude typ struktura)
Matice mAbs(Matice x);
// Absolutní hodnota komplexního čísla (Komplex je struktura)
double cAbs(Komplex x);
Takto bychom museli postupovat v jazyku C, ale v C++ máme díky možnosti přetěžování funkcí jinou možnost. Nevýhodou předchozího řešení je, že si uživatel musí pamatovat velké množství funkcí. Sice jsme se pokusili názvy zvolit dostatečně jasně, ale jak uvidíme později, lze to i jednodušeji, třeba takto (opět jenom deklarace):
// Absolutní hodnota dlouhého celého číslo
long Abs(long x);
// Asolutní hodnota reálného čísla
double Abs(double x);
// Absolutní hodnota matice (Matice bude typ struktura)
Matice Abs(Matice x);
// Absolutní hodnota komplexního čísla (Komplex je struktura)
double Abs(Komplex x);
Máme zde pouze jeden název funkce: Abs, ale jsou zde čtyři různé definice funkce (které jsme si zde neuvedli - definice funkce = tělo funkce). Je asi jasné, že definice funkcí se budou lišit, protože algoritmus výpočtu absolutní hodnoty komplexního čísla je naprosto odlišný od výpočtu absolutní hodnoty celého čísla. Překladač sám pozná při překladu volání funkce, kterou z přetížených verzí máme na mysli. Rozlišovacím znamením jsou počet nebo typy parametrů. Z toho plyne i omezení při přetěžování funkcí (nebo metod), kdy je nutné, aby se jednotlivé přetížené funkce lišily počtem parametrů nebo jejich typem.